1.概述
背景写了一段这样的代码
package com.java.thread.demo.threadlocal;import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;public class ThreadLocalStatic {private static ThreadLocal<DateFormat> df0 = ThreadLocal.withInitial(()->new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS"));private static ThreadLocal<DateFormat> df1 = new ThreadLocal<>();static {DateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");format.setTimeZone(TimeZone.getTimeZone("GTM+8"));df1.set(format);}public static String now(){return df0.get().format(new Date());}public static String now1(){DateFormat result = df1.get();return result.format(new Date());}
}
然后测试的时候如下
@Testpublic void now1() {System.out.println(ThreadLocalStatic.now());System.out.println(ThreadLocalStatic.now1());}@Testpublic void now() {for (int i = 0; i < 100; i++) {System.out.println(ThreadLocalStatic.now());System.out.println(ThreadLocalStatic.now1());}}
两个都是正常的,然后我就写到测试环境进行测试。代码是嵌入到flink中了。然后运行报错了空指针异常
public static String now1(){DateFormat result = df1.get();return result.format(new Date());}
这里result空指针异常了。这里很纳闷呀,打破我的认知了,static不是静态代码块吗?应该最先执行的呀?
然后就去查查ThreadLocal相关的,然后发现多线程下会出现这样的问题。我本地在现这个问题
package com.java.thread.demo.threadlocal;public class MyThread extends Thread {@Overridepublic void run() {System.out.println("1-" + Thread.currentThread().getName() + "\t" + ThreadLocalStatic.now());System.out.println("2-" + Thread.currentThread().getName() + "\t" + ThreadLocalStatic.now1());System.out.println("3-" + Thread.currentThread().getName() + "\t" + ThreadLocalStatic.now1());}
}
测试类如下
@Testpublic void now1Test() throws InterruptedException {MyThread a1 = new MyThread();MyThread a2 = new MyThread();a1.start();a2.start();Thread.sleep(Integer.MAX_VALUE);}
然后运行就报错了
1-Thread-1 2020-07-25 17:52:13:3111-Thread-0 2020-07-25 17:52:13:311
Exception in thread "Thread-1" java.lang.NullPointerExceptionat com.java.thread.demo.threadlocal.ThreadLocalStatic.now1(ThreadLocalStatic.java:26)at com.java.thread.demo.threadlocal.MyThread.run(MyThread.java:7)
这是因为static
只运行一次,因此只在第一个线程里面初始化后,其他线程都不会初始化了,所以才报错空指针异常。