SimpleDateFormat线程不安全的5种解决方案

1.什么是线程不安全?

线程不安全也叫非线程安全,是指多线程执行中,程序的执行结果和预期的结果不符的情况就叫着线程不安全。

线程不安全的代码

SimpleDateFormat 就是一个典型的线程不安全事例,接下来我们动手来实现一下。首先我们先创建 10 个线程来格式化时间,时间格式化每次传递的待格式化时间都是不同的,所以程序如果正确执行将会打印 10 个不同的值,接下来我们来看具体的代码实现:

import java.text.SimpleDateFormat; 
import java.util.Date; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
 
public class SimpleDateFormatExample { 
    // 创建 SimpleDateFormat 对象 
    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("mm:ss"); 
 
    public static void main(String[] args) { 
        // 创建线程池 
        ExecutorService threadPool = Executors.newFixedThreadPool(10); 
        // 执行 10 次时间格式化 
        for (int i = 0; i < 10; i++) { 
            int finalI = i; 
            // 线程池执行任务 
            threadPool.execute(new Runnable() { 
                @Override 
                public void run() { 
                    // 创建时间对象 
                    Date date = new Date(finalI * 1000); 
                    // 执行时间格式化并打印结果 
                    System.out.println(simpleDateFormat.format(date)); 
                } 
            }); 
        } 
    } 
} 

我们预期的正确结果是这样的(10 次打印的值都不同):

SimpleDateFormat线程不安全的5种解决方案

然而,以上程序的运行结果却是这样的:

SimpleDateFormat线程不安全的5种解决方案

从上述结果可以看出,当在多线程中使用 SimpleDateFormat 进行时间格式化是线程不安全的。

2.解决方案

SimpleDateFormat 线程不安全的解决方案总共包含以下 5 种:

  1. 将 SimpleDateFormat 定义为局部变量;
  2. 使用 synchronized 加锁执行;
  3. 使用 Lock 加锁执行(和解决方案 2 类似);
  4. 使用 ThreadLocal;
  5. 使用 JDK 8 中提供的 DateTimeFormat。

接下来我们分别来看每种解决方案的具体实现。

① SimpleDateFormat改为局部变量

将 SimpleDateFormat 定义为局部变量时,因为每个线程都是独享 SimpleDateFormat 对象的,相当于将多线程程序变成“单线程”程序了,所以不会有线程不安全的问题,具体实现代码如下:

 

上一篇:Timer定时任务


下一篇:时间日期类