ThreadLocalNormalUsage05,SimpleDateFormat如何做到的线程隔离?
来源:4-5 更好的做法

bfcpzk
2020-01-02
在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
写回答
2回答
-
悟空
2020-01-02
示例代码:
public String date(int seconds) { //参数的单位是毫秒,从1970.1.1 00:00:00 GMT计时 Date date = new Date(1000 * seconds); // SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat dateFormat = ThreadSafeFormatter.dateFormatThreadLocal2.get(); System.out.println( Thread.currentThread().getName() + ThreadSafeFormatter.dateFormatThreadLocal); SimpleDateFormat simpleDateFormat = ThreadSafeFormatter.dateFormatThreadLocal.get(); System.out.println(Thread.currentThread().getName() + simpleDateFormat.toString()); System.out.println( Thread.currentThread().getName() + System.identityHashCode(simpleDateFormat)); return dateFormat.format(date); }
00 -
bfcpzk
提问者
2020-01-02
如果线程池中10个线程同时访问的还是同一个SimpleDateFormat对象,如何做到的线程安全呢?
022020-01-03
相似问题