面试十二、ThreadLocal使用

1、使用场景

  1.1、静态变量如果要考虑线程安全的情况。用作保存每个线程自身的独享对象,以保证线程安全

    如下代码:结果报异常了,因为sdf线程不安全,导致部分线程获取的时间不对

// 时间工具
public class DateUtil {

    private static final SimpleDateFormat sdf = 
            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    public static Date parse(String dateStr) {
        Date date = null;
        try {
            date = sdf.parse(dateStr);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return date;
    }
}

// 调用
public static void main(String[] args) {

    ExecutorService service = Executors.newFixedThreadPool(20);

    for (int i = 0; i < 20; i++) {
        service.execute(()->{
            System.out.println(DateUtil.parse("2019-06-01 16:34:30"));
        });
    }
    service.shutdown();
}

    解决方案一:每次新new对象(下第一个类),开销太大

    解决方案二:加锁,并发上不去

    解决方案三:使用treadLocal

 1 public class DateUtil {
 2 
 3     public static Date parse(String dateStr) {
 4         SimpleDateFormat sdf =
 5                 new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 6         Date date = null;
 7         try {
 8             date = sdf.parse(dateStr);
 9         } catch (ParseException e) {
10             e.printStackTrace();
11         }
12         return date;
13     }
14 }
15 
16 public class DateUtil {
17 
18     private static final SimpleDateFormat sdf =
19             new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
20 
21     public static synchronized Date parse(String dateStr) {
22         Date date = null;
23         try {
24             date = sdf.parse(dateStr);
25         } catch (ParseException e) {
26             e.printStackTrace();
27         }
28         return date;
29     }
30 }
31 
32 public class DateUtil {
33 
34     private static ThreadLocal<DateFormat> threadLocal = ThreadLocal.withInitial(
35             ()-> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
36 
37     public static Date parse(String dateStr) {
38         Date date = null;
39         try {
40             date = threadLocal.get().parse(dateStr);
41         } catch (ParseException e) {
42             e.printStackTrace();
43         }
44         return date;
45     }
46 }

 

  1.2、用作每个线程内需要保存的独立信息,以便其他地方用到时可直接获取避免传参,类似上下文

2、使用注意

  内存泄漏,记得每次使用完都remove

posted on 2021-08-26 23:34  Iversonstear  阅读(37)  评论(0编辑  收藏  举报

导航