关于SimpleDateFormat
熟悉Java的同学知道这个类是线程不安全的,但究竟是怎样不安全法,什么原因产生的线程不安全?估计未必全部人都能够答得上来(我也不能,emmmm)
呃,想更好地了解关于 SimpleDateFormat 这个工具类的线程不安全的原因,推荐一位大佬的博客,请参考:高并发之——SimpleDateFormat类的线程安全问题和解决方案
正文
1、SimpleDateFormat 线程不安全的原因
请参考上述博文
2、解决方案
解决方案是有很多的
- 把 SimpleDateFormat 放到方法里面(不太好)
- 加 synchronized(不太好)
- 加 lock (不太好)
- 使用threadLocal (推荐)
- 使用 DateTimeFormatter (推荐)
- 使用joda-time方式(需要引入新依赖,看情况决定使用)
3、列一些demo代码
是为自己记得,参考的博文解释得更清楚些
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class SimpleDateFormatFix02 {
//执行总次数
private static final int EXECUTE_COUNT = 1000;
//同时运行的线程数量
private static final int THREAD_COUNT = 20;
private static final String DATE_FORMAT = "yyyy-MM-dd";
private static ThreadLocal<SimpleDateFormat> threadLocal = ThreadLocal.withInitial(() -> new SimpleDateFormat(DATE_FORMAT));
// ThreadLocal的另外一种写法
private static ThreadLocal<SimpleDateFormat> threadLocal2 = new ThreadLocal();
private static SimpleDateFormat getDataFormat(){
SimpleDateFormat simpleDateFormat = threadLocal2.get();
if(null == simpleDateFormat){
simpleDateFormat = new SimpleDateFormat(DATE_FORMAT);
threadLocal2.set(simpleDateFormat);
}
return simpleDateFormat;
}
// end
public static void main(String[] args) throws InterruptedException {
final Semaphore semaphore = new Semaphore(THREAD_COUNT);
final CountDownLatch countDownLatch = new CountDownLatch(EXECUTE_COUNT);
ThreadPoolExecutor executor = new ThreadPoolExecutor(THREAD_COUNT, THREAD_COUNT, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(1000));
for (int i = 0; i < EXECUTE_COUNT; i++) {
executor.execute(() -> {
try {
semaphore.acquire();
try {
threadLocal.get().parse("2022-01-01");
} catch (ParseException e) {
e.printStackTrace();
System.out.println("转换失败");
System.exit(1);
} catch (NumberFormatException e) {
e.printStackTrace();
System.out.println("转换失败");
System.exit(1);
}
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
System.exit(1);
}
countDownLatch.countDown();
});
}
countDownLatch.await();
executor.shutdown();
System.out.println("finish success!");
}
}
嗯,只记录一下ThreadLocal 的写法,其它写法就不写了。
再说多句,
关于 ThreadLocal 的写法也有几种写法,
// 写法之一
private static ThreadLocal<SimpleDateFormat> threadLocal3 = new ThreadLocal(){
@Override
protected Object initialValue() {
return new SimpleDateFormat(DATE_FORMAT);
}
};
// 写法之二
private static ThreadLocal<SimpleDateFormat> threadLocal = ThreadLocal.withInitial(() -> new SimpleDateFormat(DATE_FORMAT));
// 写法之三
private static ThreadLocal<SimpleDateFormat> threadLocal2 = new ThreadLocal();
private static SimpleDateFormat getDataFormat(){
SimpleDateFormat simpleDateFormat = threadLocal2.get();
if(null == simpleDateFormat){
simpleDateFormat = new SimpleDateFormat(DATE_FORMAT);
threadLocal2.set(simpleDateFormat);
}
return simpleDateFormat;
}
// end
嗯。好了。先记一些吧。
标签:static,simpleDateFormat,private,SimpleDateFormat,ThreadLocal,线程,new,多线程 From: https://www.cnblogs.com/aaacarrot/p/17142026.html