
原标题:java学习之多线程ThreadLocal你会用吗?
java中的java.lang.ThreadLocal,为处理多线程程序的并发问题供给了一种新的思路。运用这个东西类能够很简练地编写出美丽的多线程程序,ThreadLocal并不是一个Thread,而是Thread的局部变量。
ThreadLocal很简略让人断章取义,想当然地认为是一个“本地线程”。其实,ThreadLocal并不是一个Thread,而是Thread的局部变量,或许把它命名为ThreadLocalVariable更简略让人了解一些。
当运用ThreadLocal保护变量时,ThreadLocal为每个运用该变量的线程供给独立的变量副本,所以每一个线程都能够独登时改动自己的副本,而不可能影响其它线程所对应的副本。浅显一点,就是在每个Thread中,都有一个ThreadLocalMap调集,在该map中,key为该ThreadLocal目标,value即为ThreadLocal中变量的副本,所以ThreadLocal仅仅操作每个线程的ThreadLocalMap罢了。
ThreadLocal有三个首要办法:
public T get() { }
public void set(T value) { }
public void remove() { }
get办法的完成:
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
在get办法中,首要得到当时线程实例中保存的ThreadLocalMap,假如存在该Map,则从Map中获取key为this(当时ThreadLocal)对应的值;假如不存在该Map或Value不存在,则回来初始值。
set办法完成如下:
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
和get办法同理,先得到ThreadLocalMap,假如Map存在,则将键值对(键为this,即当时ThreadLocal)保存在该Map中;假如ThreadLocalMap不存在,则创立该Map,并保存键值对。
remove办法完成如下:
public void remove() {
ThreadLocalMap m = getMap(Thread.currentThread());
if (m != null)
m.remove(this);
}
接下来咱们结合一个比如,来加深对ThreadLocal的了解。
public class ThreadLocalDemo {
private static final ThreadLocal<Integer> localInt = new ThreadLocal<Integer>();
private static ExecutorService executorService;
static {
executorService = Executors.newFixedThreadPool(10, new ThreadFactory() {
private AtomicInteger threadCount = new AtomicInteger(0);
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("Thread-" + threadCount.incrementAndGet());
return thread;
}
});
}
public static void main(String[] args) {
AtomicInteger ai = new AtomicInteger(0);
for (int i = 0; i < 10; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
ai.incrementAndGet();
//每个线程有各自的变量副本,不会受其他线程影响。
localInt.set(ai.get());
//改动自己的副本值,不可能影响其他线程的ThreadLocal。
if(ai.get() == 1) {
localInt.set(9999);
}
System.out.println(Thread.currentThread().getName() + " " + localInt.get());
}
});
}
executorService.shutdown();
}
}
运转成果如下:
Thread-2 9999
Thread-1 2
Thread-6 4
Thread-4 3
Thread-3 5
Thread-8 6
Thread-10 7
Thread-5 8
Thread-7 9
Thread-9 10
咱们发现其间一个线程将本地的ThreadLocal变量副本设置为9999,并没有对其他线程发生任何影响。
定论:
ThreadLocal是处理线程安全问题一个很好的思路,它通过为每个线程供给一个独立的变量副本处理了变量并发拜访的抵触问题。在许多情况下,ThreadLocal比直接运用synchronized同步机制处理线程安全问题更简略,更便利,且成果程序具有更高的并发性。
灵敏运用ThreadLocal,能处理多线程环境下的线程安全问题。如在Spring中,运用了ThreadLocal处理了单例的线程安全问题;在MyBatis中,运用ThreadLocal完成了线程安全的SqlSessionManager。需求记住的是:ThreadLocal不是处理多线程环境下同享变量的拜拜访题的,而是为每个线程供给一个独立的变量副本处理了变量并发拜访的抵触问题。
最终,开发这么多年我也总结了一套学习Java的材料,假如你在技术上面想提高自己的话,能够重视我,私信发送收取材料或许在谈论区留下自己的联系方式,有时间记住帮我点下转发让跟多的人看到哦。
责任编辑:








