ThreadLocal 的最佳实践
  JAVA2 分钟读完 (大约342个字) SimpleDateFormat 众所周知是线程不安全的,多线程中如何保证线程安全又同时兼顾性能问题呢?那就是使用 ThreadLocal 维护 SimpleDateFormat
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
   | public class SimpleDateFormatThreadTest {
      static volatile AtomicInteger n = new AtomicInteger(-1);
  <!-- more -->
      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 的好处也就立竿见影了。