在ThreadLocalNormalUsage05中,打印ThreadLocal和SimpleDateFormat对象,发现都是同一个对象,我的理解是线程池中的10个线程应该是创建了10个ThreadLocalMap,每个map中都存了一个Entry,key是同一个ThreadLocal对象的引用,value也都是同一个SimpleDateFormat对象,并没有看到副本的拷贝,但却保证了线程的隔离,这是如何做到的呢?
public class ThreadLocalNormalUsage05 {
private static ExecutorService threadPool = Executors.newFixedThreadPool(10);
public static void main(String[] args) {
for (int i = 0 ; i < 1000 ; i++) {
int finalI = i;
threadPool.submit(new Runnable() {
public void run() {
String date = new ThreadLocalNormalUsage05().date(finalI);
System.out.println(date);
}
});
}
threadPool.shutdown();
}
private String date(int seconds) {
//单位是毫秒
Date date = new Date(seconds * 1000);
SimpleDateFormat sdf = ThreadSafeDateFormatter.dateFormatThreadLocal.get();
System.out.println(ThreadSafeDateFormatter.dateFormatThreadLocal);
System.out.println(ThreadSafeDateFormatter.dateFormatThreadLocal.get());
return sdf.format(date);
}
}
class ThreadSafeDateFormatter {
static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal = new ThreadLocal<SimpleDateFormat>(){
protected SimpleDateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
};
static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal2 = ThreadLocal.withInitial(
() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
}
运行结果:
threadlocal.ThreadSafeDateFormatter$1@46600188
threadlocal.ThreadSafeDateFormatter$1@46600188
java.text.SimpleDateFormat@4f76f1a0
threadlocal.ThreadSafeDateFormatter$1@46600188
java.text.SimpleDateFormat@4f76f1a0
threadlocal.ThreadSafeDateFormatter$1@46600188
java.text.SimpleDateFormat@4f76f1a0
threadlocal.ThreadSafeDateFormatter$1@46600188
java.text.SimpleDateFormat@4f76f1a0
threadlocal.ThreadSafeDateFormatter$1@46600188
threadlocal.ThreadSafeDateFormatter$1@46600188
java.text.SimpleDateFormat@4f76f1a0
threadlocal.ThreadSafeDateFormatter$1@46600188
java.text.SimpleDateFormat@4f76f1a0
java.text.SimpleDateFormat@4f76f1a0
1970-01-01 08:00:07
1970-01-01 08:00:02
threadlocal.ThreadSafeDateFormatter$1@46600188
threadlocal.ThreadSafeDateFormatter$1@46600188
java.text.SimpleDateFormat@4f76f1a0
threadlocal.ThreadSafeDateFormatter$1@46600188
java.text.SimpleDateFormat@4f76f1a0
java.text.SimpleDateFormat@4f76f1a0
1970-01-01 08:00:08
1970-01-01 08:00:00
1970-01-01 08:00:01
1970-01-01 08:00:06
1970-01-01 08:00:04
1970-01-01 08:00:09