一、ThreadLocal是什么
ThreadLocal是線程本地存儲(chǔ)變量剩檀,線程將一些變量存儲(chǔ)在ThreadLocal對(duì)象中澄干。
二、ThreadLocal的用法
ThreadLocal因?yàn)橹皇欠啪€程自身的需要使用的變量跷跪,這些變量只有線程自身能夠訪問馋嗜,所以并不能解決多線程并發(fā)的問題。那么ThreadLocal在什么場景下使用呢域庇?
先看一個(gè)常用的例子:
public class ConnectionManager {
private static String url ="***";
private static Connection connect = null;
public static Connection openConnection() throws SQLException {
if(connect == null){
connect = DriverManager.getConnection(url);
}
return connect;
}
public static void closeConnection() throws SQLException {
if(connect!=null)
connect.close();
}
}
獲取數(shù)據(jù)庫連接嵌戈,這是我們剛開始學(xué)習(xí)jdbc的用法,簡單使用是沒有問題的听皿。但還是有兩個(gè)問題無法解決:
- 高并發(fā)的情況下熟呛,可能多個(gè)線程同時(shí)獲取到數(shù)據(jù)庫連接,就會(huì)產(chǎn)生并發(fā)的問題尉姨。我們想到可以使用同步鎖來處理庵朝,保證只有一個(gè)線程獲取到數(shù)據(jù)庫連接,但這樣毫無疑問效率非常低又厉。
- 如果有多條sql需要執(zhí)行九府,需要用同一個(gè)connection對(duì)象。那就需要在多個(gè)方法中傳遞這個(gè)connection對(duì)象覆致,方法傳遞會(huì)有點(diǎn)麻煩侄旬。
那么有沒有更好的方法呢,就是本文講到的ThreadLocal了煌妈。我們稍微修改一下:
public class ConnectionManager {
private static String url ="***";
private static final ThreadLocal<Connection> threadLocal = new ThreadLocal<Connection>();
public static Connection openConnection() throws SQLException {
Connection connect = threadLocal.get();
if(connect == null){
connect = DriverManager.getConnection(url);
threadLocal.set(connect);
}
return connect;
}
}
使用了ThreadLocal后儡羔,由于線程訪問的都是自己的Connection對(duì)象宣羊,所以就不存在高并發(fā)的問題。同時(shí)還解決了事務(wù)的問題汰蜘,同一個(gè)事務(wù)里仇冯,Connection對(duì)象不需要傳來傳去,直接用ThreadLocal獲取就可以了族操。
所以我們總結(jié)一下ThreadLocal的兩點(diǎn)好處:
- 每個(gè)線程有自己的ThreadLocalMap對(duì)象苛坚,線程各自訪問各自的,提供了保存對(duì)象到線程的方法色难。
- 減少了線程間傳遞參數(shù)的麻煩泼舱。
基于這樣兩點(diǎn)好處,我們在獲取數(shù)據(jù)庫連接莱预,獲取session柠掂,獲取token信息等場景下使用ThreadLocal會(huì)很方便。