Java并发编程学习八:ThreadLocal
一、ThreadLocal使用场景
Java为保证并发情况下的线程安全,提供了多种可用的方案,典型的如:各种锁(包括synchronize关键字)、原子类、ThreadLocal类等。前面对锁以及原子类已经进行了较为详细的介绍,这里继续介绍ThreadLocal。
ThreadLocal 有两种典型的使用场景:
- 场景1:用作保存每个线程独享的对象,为每个线程都创建一个 副本,每个线程都可以修改自己所拥有的副本, 而不会影响其他线程的副本,确保了线程安全。
- 场景2:用作每个线程内需要独立保存的信息,以便供线程内其他方法更方便地获取该信息。线程内前面执行的方法保存了信息后,后续方法可以通过 ThreadLocal 直接获取到,避免了传参,类似于全局变量的概念
1. 用作线程独享的对象
以这样一个场景为例:多个线程,要求每个线程打印的时间不重复,这里需要借助SimpleDateFormat类,该类是一个线程不安全的工具类。
如果线程数为1000,这些线程共享一个SimpleDateFormat对象,由于SimpleDateFormat类是线程不安全的,为了保证线程安全,必然要加上锁。
public class ThreadLocalDemo01 {
public static ExecutorService threadPool = Executors.newFixedThreadPool(16);
static SimpleDateFormat dateFormat = new SimpleDateFormat("mm:ss");
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 1000; i++) {
int finalI = i;
threadPool.submit(new Runnable() {
@Override
public void run() {
String date = new ThreadLocalDemo01().date(finalI);
System.out.println(date);
}
});
}
threadPool.shutdown();
}
public String date(int seconds) {
Date date = new Date(1000 * seconds);
String s = null;
synchronized (ThreadLocalDemo01.class) {
s = dateFormat.format(date);
}
return s;
}
}