ThreadLocal的一些學習理解

ThreadLocal
1、 多線程同時訪問統一共享屬性的時候產生的線程安全問題的一種解決方案,適用於每個線程對這個共享屬性的修改都不會影響到其他線程,即不需要線程間通信的這種情況;這樣做是爲了避免使用同步鎖導致的效率問題(每個線程各創建一個共享數據的副本分別服務於各自的線程);

2、 每個Thread內部有兩個類似Map的屬性ThreadLocalMap,通過Thread.currentThread();獲取當前的線程實例,再獲取本線程中的Map實例,通過對這個Map中進行數據的增刪,實現共享數據的副本和線程綁定的目的,從而在一定程度上避免線程安全問題。

簡單來說,ThreadLocal是將一些複雜的系統擴展變成了簡單定義,使得相關參數牽連的部分變得非常容易,以下是我們例子說明:
Spring的事務管理器中,對數據源獲取的Connection放入了ThreadLocal中,程序執行完後由ThreadLocal中獲取connection然後做commit和rollback,使用中,要保證程序通過DataSource獲取的connection就是從spring中獲取的,爲什麼要做這樣的操作呢,因爲業務代碼完全由應用程序來決定,而框架不能要求業務代碼如何去編寫,否則就失去了框架不讓業務代碼去管理connection的好處了,此時業務代碼被切入後,spring不會向業務代碼區傳入一個connection,它必須保存在一個地方,當底層通過ibatis、spring jdbc等框架獲取同一個datasource的connection的時候,就會調用按照spring約定的規則去獲取,由於執行過程都是在同一個線程中處理,從而獲取到相同的connection,以保證commit、rollback以及業務操作過程中,使用的connection是同一個,因爲只有同一個conneciton才能保證事務,否則數據庫本身也是不支持的。


最常見的ThreadLocal使用場景爲 用來解決 數據庫連接、Session管理等。


private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>() {
    public Connection initialValue() {
        return DriverManager.getConnection(DB_URL);
    }
};
 
public static Connection getConnection() {
    return connectionHolder.get();
}
private static final ThreadLocal threadSession = new ThreadLocal();
 
public static Session getSession() throws InfrastructureException {
    Session s = (Session) threadSession.get();
    try {
        if (s == null) {
            s = getSessionFactory().openSession();
            threadSession.set(s);
        }
    } catch (HibernateException ex) {
        throw new InfrastructureException(ex);
    }
    return s;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章