美文网首页
ThreadLocal解决线程安全

ThreadLocal解决线程安全

作者: 小土豆1994 | 来源:发表于2019-12-31 15:26 被阅读0次

    线程不安全示例

    /**
     * 描述:     1000个打印日期的任务,用线程池来执行
     */
    public class ThreadLocalNormalUsage03 {
    
        public static ExecutorService threadPool = Executors.newFixedThreadPool(10);
        static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
        public static void main(String[] args) throws InterruptedException {
            for (int i = 0; i < 1000; i++) {
                int finalI = i;
                threadPool.submit(new Runnable() {
                    @Override
                    public void run() {
                        String date = new ThreadLocalNormalUsage03().date(finalI);
                        System.out.println(date);
                    }
                });
            }
            threadPool.shutdown();
        }
    
        public String date(int seconds) {
            //参数的单位是毫秒,从1970.1.1 00:00:00 GMT计时
            Date date = new Date(1000 * seconds);
            return dateFormat.format(date);
        }
    }
    
    运行结果
    1. SimpleDateFormat 是不安全的,被多个线程共用情况下。

    使用ThreadLocal解决

    /**
     * 描述:     利用ThreadLocal,给每个线程分配自己的dateFormat对象,保证了线程安全,高效利用内存
     */
    public class ThreadLocalNormalUsage05 {
    
        public static ExecutorService threadPool = Executors.newFixedThreadPool(10);
    
        public static void main(String[] args) throws InterruptedException {
            for (int i = 0; i < 1000; i++) {
                int finalI = i;
                threadPool.submit(new Runnable() {
                    @Override
                    public void run() {
                        String date = new ThreadLocalNormalUsage05().date(finalI);
                        System.out.println(date);
                    }
                });
            }
            threadPool.shutdown();
        }
    
        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();
            return dateFormat.format(date);
        }
    }
    
    //下面两种方法功能一样,实现方式不同
    class ThreadSafeFormatter {
    
        public static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal = new ThreadLocal<SimpleDateFormat>() {
            @Override
            protected SimpleDateFormat initialValue() {
                return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            }
        };
    
        public static ThreadLocal<SimpleDateFormat> dateFormatThreadLocal2 = ThreadLocal
                .withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    }
    
    运行结果
    1. 利用ThreadLocal,给每个线程分配自己的dateFormat对象,保证了线程安全,高效利用内存

    相关文章

      网友评论

          本文标题:ThreadLocal解决线程安全

          本文链接:https://www.haomeiwen.com/subject/dmsboctx.html