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

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

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

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 西西人体大胆啪啪私拍色约约 | 欧美成人免费观看bbb | 日本高清有码视频 | 国产农村一级特黄α真人毛片 | 欧美亚洲国产综合在线 | 白丝女仆被啪到深夜漫画 | 日本九九热 | 国产九九在线观看播放 | 91在线亚洲综合在线 | 91精品啪在线观看国产线免费 | 国产高清一区二区三区免费视频 | 欧美sq| 狠狠久久久久综合网 | 欧美一级高清片免费一级 | 日本成年片高清在线观看 | 亚洲男人天堂影院 | 国产欧美一区二区三区免费看 | 男人躁女人过程 | 爱操综合网| 91丝袜足控免费网站xx | 国产精品最新资源网 | 91久久线看在观草草青青 | 我和寂寞孕妇的性事 | 日本免费v片一二三区 | 美女脱一光二净的视频 | 精品午夜中文字幕熟女人妻在线 | 成人女人天堂午夜视频 | 亚洲一卡2卡三卡4卡5卡组 | 青春草在线观看精品免费视频 | 女人扒开下面让男人桶爽视频 | 4444kk在线看片| 爱福利一区二区 | 女八把屁股扒开让男生添 | 日本一区二区三区在线 观看网站 | 成人精品免费网站 | 欧美日韩一区二区三区韩大 | 四虎1515hhh co m | 色伦网 | 亚洲精品国产在线 | 我和岳的性事小说 | 从后面撕开老师的丝袜动态图 |