在《多线程采用锁并发控制》一文中采用锁保证了多线程下类的成员变量的同步。如果需要保证线程内部对变量的访问是隔离的,线程内部对变量的操作不会影响其他的线程,这又该如何操作了。ThreadLocal对象通常用于防止对可变的单实例变量或全局变量进行共享。
public class MyCounter implements Runnable {
private static ThreadLocal<Long> count = new ThreadLocal<Long>(){
public Long initialValue() {
return 0L;
}
};
public Long getNext() {
count.set(count.get()+1);
return count.get();
}
public synchronized void run() {
System.out.println("thread id:"+Thread.currentThread().getId()+",count:"+getNext());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
MyCounter countThread = new MyCounter();
for(int i=0; i<9; i++){
executorService.submit(countThread);
}
}
}
上面的程序通过ThreadLocal实现了计数器的初始化,在线程的run方法中打印出当前的执行线程和计数器的下一个值。看看程序运行的某一次结果。
thread id:10,count:1
thread id:12,count:1
thread id:11,count:1
thread id:12,count:2
thread id:10,count:2
thread id:12,count:3
thread id:11,count:2
thread id:12,count:4
thread id:10,count:3
从结果中可以看出线程10,11,12获取的计数值都是独立递增的。这实现了我们的期望,线程之前的操作是隔离的,每个线程获取独立的值。ThreadLocal特别适用于长流程中的上下文的实现,在长流程中可以将变量的值放入上下文中进行共享,后面的流程可以共享前面的数据。