存在线程安全问题怎么修改bug

public class App {

    public static void main( String[] args )
    {
        ExecutorService executorService = Executors.newCachedThreadPool();
        List<String> dateStrList = Lists.newArrayList(
                "2018-04-01 10:00:01",
                "2018-04-02 11:00:02",
                "2018-04-03 12:00:03",
                "2018-04-04 13:00:04",
                "2018-04-05 14:00:05"
        );
        final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
        for (final String str : dateStrList) {
            executorService.execute(new Runnable() {

                public void run() {
                    // TODO Auto-generated method stub
                    try {
                        System.out.println(simpleDateFormat.parse(str));
                        TimeUnit.SECONDS.sleep(1);
                    } catch ( Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }
            });

        }

    }
}

SimpleDateFormat是线程不安全的,需放在run()方法内部。或者考虑使用threadlocal封装,可参考 DateUtil
https://github.com/zxiaofan/JavaUtils/blob/master/src/com/zxiaofan/util/other/DateUtil.java

首先,这段代码运行时会产生这个运行时异常:

java.lang.NumberFormatException: multiple points
    at sun.misc.FloatingDecimal.readJavaFormatString(Unknown Source)

根源就是 SimpleDateFormat 的线程不安全导致多线程共享该对象时产生了多指向问题。
其次,这里用了线程池提交任务,而任务执行完成后没有关闭线程池对象,导致程序存在资源泄露问题,应该等待所有任务执行完成后关闭线程池。

for (final String str : dateStrList) {
                executorService.execute(new Runnable() {
                    public void run() {
                        try {
                            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            System.out.println(simpleDateFormat.parse(str));
                            TimeUnit.SECONDS.sleep(1);
                        } catch ( Exception e) {
                            e.printStackTrace();
                        }

                    }
                });

            }

            executorService.shutdown();