并发编程基础之ThreadLocal
2024-09-29 12:28:32
一:概念
在多线程并发访问的情况下,为了解决线程安全,一般我们会使用synchronized关键字,如果并发访问量不是很大,可以使用synchronized,
但是如果数据量比较大,我们可以考虑使用ThreadLocal,顾名思义,就是线程的本地存储,对于类中的成员变量,如果多个线程同时访问
就会存在线程安全问题,ThreadLocal提供给我们不同于synchronized的另外一种思路,就是把变量值在每个线程存储副本
如下示例:
/**
*
*/
package com.hlcui.main; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; /**
* @author Administrator
*
*/
public class ThreadLocalDemo { //保留变量在线程中的副本
private ThreadLocal<String> threadLocal = new ThreadLocal<String>(); private void set(String name) {
threadLocal.set(name);
} private String get() {
return threadLocal.get();
} public static void main(String[] args) {
final ThreadLocalDemo demo = new ThreadLocalDemo(); ExecutorService executors = Executors.newFixedThreadPool(2);
executors.execute(new Runnable() {
@Override
public void run() {
demo.set("tom");
String threadName = Thread.currentThread().getName();
System.out.println(threadName+":::"+demo.get());
}
}); executors.execute(new Runnable() {
@Override
public void run() {
demo.set("jack");
String threadName = Thread.currentThread().getName();
System.out.println(threadName+":::"+demo.get());
}
}); executors.shutdown();
}
}
运行结果:
pool-1-thread-1:::tom
pool-1-thread-2:::jack
通过结果可以看出同一个实例的同一个方法,不同的线程获取的结果是不一样的。
示例二:
测试5个线程计数:
/**
*
*/
package com.hlcui.main; import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit; /**
* @author Administrator
*
*/
public class ThreadDemo2 {
public static void main(String[] args) {
ExecutorService executors = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
executors.execute(new ThreadHolder(i));
}
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
executors.shutdown();
} } class ThreadHolder implements Runnable { private final int id; ThreadHolder(int i) {
this.id = i;
} private static ThreadLocal<Integer> tl = new ThreadLocal<Integer>() {
Random r = new Random(47);
public synchronized Integer initialValue() {
return r.nextInt(100);
}
}; public static void increment() {
tl.set(tl.get() + 1);
} @Override
public void run() {
System.out.println(this);
ThreadHolder.increment();
System.out.println(this);
} public String toString() {
return "id:::"+id+", "+tl.get();
} }
运行结果:
id:::0, 58
id:::1, 55
id:::2, 93
id:::0, 59
id:::2, 94
id:::1, 56
id:::3, 61
id:::3, 62
id:::4, 61
id:::4, 62
最新文章
- 在UWP中页面滑动导航栏置顶
- Your account already has a valid iOS Distribution certificate!
- 在github上写个人简历——先弄个主页
- Ext.GridPanel 用法总结(一)—— Grid基本用法
- JS初学之-自定义属性(索引值)
- 为什么选择 Yeoman 及 Yeoman 的安装
- PHP7正式版测试,性能惊艳!
- Android项目的图标
- Oracle EBS-SQL (WIP-14):检查车间需求与BOM差异对照.sql
- 用MVC+EF快速弄出一个CRUD
- 新版elasticsearch的插件安装
- 如何将多个C文件链接在一起----Makefile编写及make指令
- 【题解】Luogu P4867 Gty的二逼妹子序列
- JAVA高级篇(四、JVM垃圾回收和调优)
- 富可视M310刷机包 MIUIV5 红米开发版 闪光 美化 稳定
- rename 表
- norbert-构建服务器集群感知的 Java 应用程序
- Visual Assist X 10.8.2042的Crack破解补丁. 2014.06.25 (General release.)
- Java Spring-注解进行属性注入
- cuDNN下载地址和指南