一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - java中ThreadLocal的應用場景實例分析

java中ThreadLocal的應用場景實例分析

2021-08-08 15:22小妮淺淺 Java教程

在本篇文章里小編給大家整理的是一篇關于java中ThreadLocal的應用場景實例分析,對此有興趣的朋友們可以學習參考下。

說到線程的安全,我們可以通過ThreadLocal來解決。但作為一種強大的變量,它的應用場景遠不止如此。在各類的框架中,我們依然可以使用來對它們進行管理。同時在使用ThreadLocal時需要注意內存泄漏的問題。下面我們就這兩點進行分析,并帶來對應代碼的展示。

1、各種框架中的應用

Spring框架的事務管理中使用ThreadLocal來管理連接,每個線程是單獨的連接,當事務失敗時不能影響到其他線程的事務過程或結果,還有大家耳聞目睹的ORM框架、Mybatis也是用ThreadLocal管理,SqlSession也是如此。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//Spring TransactionSynchronizationManager類
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
  DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
  Connection con = null;
  try {
    //此處省略N行代碼
    if (txObject.isNewConnectionHolder()) {
      //綁定數據庫連接到線程中
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
    }
  }
  catch (Throwable ex) {
    if (txObject.isNewConnectionHolder()) {
      //當發生異常時,移除線程中的連接
      DataSourceUtils.releaseConnection(con, obtainDataSource());
      txObject.setConnectionHolder(null, false);
    }
    throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
  }
}

2、防止內存泄漏

通常我們是使用如下的方式操作ThreadLocal,在使用完threadlocal后一定要remove掉,防止內存泄露。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private static final ThreadLocal<LoginUser> loginUserLocal = new ThreadLocal<LoginUser>();
public static LoginUser getLoginUser() {
  return loginUserLocal.get();
}
public static void setLoginUser(LoginUser loginUser) {
  loginUserLocal.set(loginUser);
}
public static void clear() {
  loginUserLocal.remove();
}
//在使用完后一定要清理防止內存泄露
try{
  loginUserLocal.set(loginUser);
  //執行其他業務邏輯
}finally{
  loginUserLocal.remove();
}

java中ThreadLocal實例擴展:

?
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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/**
 * 日期工具類(使用了ThreadLocal獲取SimpleDateFormat,其他方法可以直接拷貝common-lang)
 * @author Niu Li
 * @date 2016/11/19
 */
public class DateUtil {
 
 private static Map<String,ThreadLocal<SimpleDateFormat>> sdfMap = new HashMap<String, ThreadLocal<SimpleDateFormat>>();
 
 private static Logger logger = LoggerFactory.getLogger(DateUtil.class);
 
 public final static String MDHMSS = "MMddHHmmssSSS";
 public final static String YMDHMS = "yyyyMMddHHmmss";
 public final static String YMDHMS_ = "yyyy-MM-dd HH:mm:ss";
 public final static String YMD = "yyyyMMdd";
 public final static String YMD_ = "yyyy-MM-dd";
 public final static String HMS = "HHmmss";
 
 /**
  * 根據map中的key得到對應線程的sdf實例
  * @param pattern map中的key
  * @return 該實例
  */
 private static SimpleDateFormat getSdf(final String pattern){
  ThreadLocal<SimpleDateFormat> sdfThread = sdfMap.get(pattern);
  if (sdfThread == null){
   //雙重檢驗,防止sdfMap被多次put進去值,和雙重鎖單例原因是一樣的
   synchronized (DateUtil.class){
    sdfThread = sdfMap.get(pattern);
    if (sdfThread == null){
     logger.debug("put new sdf of pattern " + pattern + " to map");
     sdfThread = new ThreadLocal<SimpleDateFormat>(){
      @Override
      protected SimpleDateFormat initialValue() {
       logger.debug("thread: " + Thread.currentThread() + " init pattern: " + pattern);
       return new SimpleDateFormat(pattern);
      }
     };
     sdfMap.put(pattern,sdfThread);
    }
   }
  }
  return sdfThread.get();
 }
 
 /**
  * 按照指定pattern解析日期
  * @param date 要解析的date
  * @param pattern 指定格式
  * @return 解析后date實例
  */
 public static Date parseDate(String date,String pattern){
  if(date == null) {
   throw new IllegalArgumentException("The date must not be null");
  }
  try {
   return getSdf(pattern).parse(date);
  } catch (ParseException e) {
   e.printStackTrace();
   logger.error("解析的格式不支持:"+pattern);
  }
  return null;
 }
 /**
  * 按照指定pattern格式化日期
  * @param date 要格式化的date
  * @param pattern 指定格式
  * @return 解析后格式
  */
 public static String formatDate(Date date,String pattern){
  if (date == null){
   throw new IllegalArgumentException("The date must not be null");
  }else {
   return getSdf(pattern).format(date);
  }
 }
}

到此這篇關于java中ThreadLocal的應用場景實例分析的文章就介紹到這了,更多相關java中ThreadLocal的應用場景淺析內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://www.py.cn/java/jichu/23818.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产一二三区视频 | 91久久精品国产亚洲 | 亚洲欧美成人综合久久久 | 秒播影视 午夜福利毛片 | 久久精品国产欧美日韩99热 | 91啦在线视频 | 男人jj视频 | 色视频久久| 免费一级欧美大片在线观看 | 日韩欧美精品一区二区 | 牛牛影院成人免费网页 | 驯服有夫之妇HD中字日本 | 国产自在自拍 | 亚洲高清在线视频 | dyav午夜片| 我的漂亮朋友在线观看全集免费 | 日本在线视频网 | 亚洲精品国产精品麻豆99 | 京东热在线观看 | 欧美日韩综合网在线观看 | 美女女女女女女bbbbbb毛片 | 毛片在线播放a | 亚洲成色 | 精品无人区麻豆乱码1区2 | 亚洲乱码一二三四五六区 | 亚洲国产欧美在线成人aaaa | 亚洲精品一区二区观看 | 久久久久久久久人体 | 99热资源| 欧美一二区视频 | 18捆绑调教在线高清 | 午夜性爽视频男人的天堂在线 | 美女把小内内脱个精光打屁屁 | 日韩一级片在线观看 | 久久国产免费 | 亚洲天天综合 | 色婷婷婷丁香亚洲综合不卡 | 日本高清二三四本2021 | 欧美又大又粗又长又硬 | 白丝校花好湿好紧 | 亚洲成人黄色网址 |