ThreadLocal在项目中的最佳实践

simpleDateFormat众所周知是线程不安全的,多线程中如何保证线程安全又同时兼顾性能问题呢?那就是使用ThreadLocal维护simpleDateFormat

public class SimpleDateFormatThreadTest {

    static volatile AtomicInteger n = new AtomicInteger(-1);

    static ThreadLocal<DateFormat> sdf ;

    static {
        sdf =new ThreadLocal<DateFormat>() {
            @Override
            protected DateFormat initialValue() {
                return new SimpleDateFormat("yyyy-MM-dd");
            }
        };
    }

    public static void main(String[] args) throws ParseException, InterruptedException {

        Set<String> dateSet = new ConcurrentHashSet<>();
        Set<Integer> numberSet = new ConcurrentHashSet<>();

        Date[] dates = new Date[1000];
        for (int i = 0; i < 1000; i++) {
            dates[i] = sdf.get().parse(i + 1000 + "-11-22");
        }

        ExecutorService executorService = Executors.newFixedThreadPool(10);
        for(int i=0;i<1000;i++){
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    int number = n.incrementAndGet();
                    String date = sdf.get().format(dates[number]);
                    numberSet.add(number);
                    dateSet.add(date);
                    System.out.println(number+" "+date);
                }
            });
        }
        executorService.shutdown();
        Thread.sleep(5000);
        System.out.println(dateSet.size());
        System.out.println(numberSet.size());
    }

}

实践证明sdf的parse(String to Date)有严重的线程安全问题,format(Date to String)有轻微的线程安全问题,虽然不太明显,但还是会出现问题,这和内部的实现有关。

简单分析下使用ThreadLocal的好处,1000次转换操作,10个线程争抢执行,如果每次都去new 一个sdf,可见其效率之低,而使用ThreadLocal,是对每个线程维护一个sdf,所以最多就只会出现10个sdf,真正项目中,由于操作系统线程分片执行,所以线程不会非常的多,使用ThreadLocal的好处也就立竿见影了。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值