首頁 Java java教程 詳解java中ThreadLocal本地線程和同步機制的比較實例

詳解java中ThreadLocal本地線程和同步機制的比較實例

Mar 23, 2017 am 10:28 AM

這篇文章主要介紹了java 中ThreadLocal本地線程和同步機制的比較的相關資料,需要的朋友可以參考下

ThreadLocal的設計

首先看看ThreadLocal的介面

Object get() ; // 返回当前线程的线程局部变量副本 protected Object
initialValue(); // 返回该线程局部变量的当前线程的初始值          
void set(Object value); // 设置当前线程的线程局部变量副本的值
登入後複製

  ThreadLocal有3個方法,其中值得注意的是initialValue(),該方法是一個protected的方法,顯然是為了子類別重寫而刻意實現的。此方法傳回目前執行緒在該執行緒局部變數的初始值,這個方法是延遲呼叫方法,在一個執行緒第1次呼叫get()或set(Object)時才執行,並且只執行1次。 ThreadLocal中的確實實作直接回傳一個null

protected Object initialValue() { return null; }
登入後複製

  ThreadLocal是如何做到為每個執行緒維護變數的副本的呢?其實實作的想法很簡單,在ThreadLocal類別中有一個Map,用來儲存每個執行緒的變數的副本。

例如下面的範例實作:就相當於存Map 這個是ThreadLocal的get方法的實作

public T get() {
    Thread t = Thread.currentThread();//获取当前线程
    ThreadLocalMap map = getMap(t);
    if (map != null) {
      ThreadLocalMap.Entry e = map.getEntry(this);
      if (e != null)
        return (T)e.value;
    }
    return setInitialValue();
  }
  
  
   ThreadLocalMap getMap(Thread t) {
    return t.threadLocals;
  }
登入後複製

ThreadLocal與其它同步機制的比較

  ThreadLocal和其它同步機制相比有什麼優點呢? ThreadLocal和其它所有的同步機制都是為了解決多線程中的對同一變數的存取衝突,在普通的同步機制中,是透過物件加鎖來實現多個執行緒對同一變數的安全存取的。這時該變數是多個執行緒共享的,使用這種同步機制需要很細緻地分析在什麼時候對變數進行讀寫,什麼時候需要鎖定某個對象,什麼時候釋放該對象的鎖等等很多。所有這些都是因為多個執行緒共享了資源造成的。 ThreadLocal就從另一個角度來解決多線程的並發訪問,ThreadLocal會為每一個線程維護一個和該線程綁定的變量的副本,從而隔離了多個線程的數據,每一個線程都擁有自己的變量副本,從而也就沒有必要對該變數進行同步了。 ThreadLocal提供了一個線程安全的共享對象,在編寫多線程程式碼時,可以把不安全的整個變數封裝進ThreadLocal,或者把該對象的特定於線程的狀態封裝進ThreadLocal。

  由於ThreadLocal中可以持有任何類型的對象,所以使用ThreadLocal get當前線程的值是需要強制類型轉換。但隨著新的Java版本(1.5)將模版的引入,新的支援模版參數的ThreadLocal類別將從中受益。也可以減少強制類型轉換,並將一些錯誤檢查提前到了編譯期,將一定程度地簡化ThreadLocal的使用。

總結

    當然ThreadLocal並不能取代同步機制,兩者面向的問題領域不同。同步機制是為了同步多個執行緒對相同資源的並發訪問,是為了多個執行緒之間進行通訊的有效方式;而ThreadLocal是隔離多個執行緒的資料共享,從根本上就不在多個執行緒之間共享資源(變數),這樣當然不需要對多個執行緒進行同步了。所以,如果你需要進行多個線程之間進行通信, 則使用同步機制;如果需要隔離多個線程之間的共享衝突,可以使用ThreadLocal,這將極大地簡化你的程序,使程序更加易讀、簡潔。

ThreadLocal常見用途:

#儲存目前session使用者
存放一些context變數,例如webwork的ActionContext
#存放session,例如Spring hibernate orm的session

範例:用ThreadLocal 實作每執行緒Singleton

       執行緒局部變數常被用來描繪有狀態「單子」(Singleton ) 或線程安全的共享對象,或者是透過把不安全的整個變數封裝進ThreadLocal,或者是透過把對象的特定於線程的狀態封裝進ThreadLocal。例如,在與資料庫有緊密聯繫的應用程式中,程式的許多方法可能都需要存取資料庫。在系統的每個方法中都包含一個 Connection 作為參數是不方便的 — 用「單子」來存取連接可能是一個雖然更粗糙,但卻方便得多的技術。然而,多個執行緒不能安全地共用一個 JDBC Connection。如清單 3 所示,透過使用「單子」中的 ThreadLocal,我們就能讓我們的程式中的任何類別輕鬆取得每個執行緒 Connection 的一個引用。這樣,我們可以認為 ThreadLocal 允許我們建立每個線程單子。

package org.heinrich.app.connection;

import java.sql.Connection;

public class ConnectionUtils {
 
 
 private final static ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
 
 
 public Connection getConnection(){
 Connection connection = threadLocal.get();
 if(connection ==null){
  connection = new DBHelper().getConn();
  threadLocal.set(connection);
 }
 
 return connection;
 }
 
 

}

package org.heinrich.app.connection;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
//数据库连接
public class DBHelper {
 public static final String url = "jdbc:mysql://localhost:3306/fk_test";
 public static final String name = "com.mysql.jdbc.Driver";
 public static final String user = "root";
 public static final String password = "root";

 public Connection conn = null;

 public Connection getConn() {
 try {
  Class.forName(name);// 指定连接类型
  conn = DriverManager.getConnection(url, user, password);// 获取连接
 } catch (Exception e) {
  e.printStackTrace();
 }
 return conn;
 }

}
登入後複製

簡單的實作Mysql連接線程安全的一種方式

理論上,ThreadLocal是的確是相對於每個線程,每個線程都會有自己的ThreadLocal。但是上面已經講到,一般的應用程式伺服器都會維護一套執行緒池。因此,不同使用者訪問,可能會接受到相同的執行緒。因此,在做基於TheadLocal時,需要謹慎,避免出現ThreadLocal變數的快取,導致其他執行緒存取到本執行緒變數。

以上是詳解java中ThreadLocal本地線程和同步機制的比較實例的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

突破或從Java 8流返回? 突破或從Java 8流返回? Feb 07, 2025 pm 12:09 PM

Java 8引入了Stream API,提供了一種強大且表達力豐富的處理數據集合的方式。然而,使用Stream時,一個常見問題是:如何從forEach操作中中斷或返回? 傳統循環允許提前中斷或返回,但Stream的forEach方法並不直接支持這種方式。本文將解釋原因,並探討在Stream處理系統中實現提前終止的替代方法。 延伸閱讀: Java Stream API改進 理解Stream forEach forEach方法是一個終端操作,它對Stream中的每個元素執行一個操作。它的設計意圖是處

PHP:網絡開發的關鍵語言 PHP:網絡開發的關鍵語言 Apr 13, 2025 am 12:08 AM

PHP是一種廣泛應用於服務器端的腳本語言,特別適合web開發。 1.PHP可以嵌入HTML,處理HTTP請求和響應,支持多種數據庫。 2.PHP用於生成動態網頁內容,處理表單數據,訪問數據庫等,具有強大的社區支持和開源資源。 3.PHP是解釋型語言,執行過程包括詞法分析、語法分析、編譯和執行。 4.PHP可以與MySQL結合用於用戶註冊系統等高級應用。 5.調試PHP時,可使用error_reporting()和var_dump()等函數。 6.優化PHP代碼可通過緩存機制、優化數據庫查詢和使用內置函數。 7

c 多線程三種實現方式的區別是什麼 c 多線程三種實現方式的區別是什麼 Apr 03, 2025 pm 03:03 PM

多線程是計算機編程中的重要技術,用來提升程序執行效率。在 C 語言中,有多種實現多線程的方式,包括線程庫、POSIX 線程和 Windows API。

PHP與Python:了解差異 PHP與Python:了解差異 Apr 11, 2025 am 12:15 AM

PHP和Python各有優勢,選擇應基於項目需求。 1.PHP適合web開發,語法簡單,執行效率高。 2.Python適用於數據科學和機器學習,語法簡潔,庫豐富。

Java程序查找膠囊的體積 Java程序查找膠囊的體積 Feb 07, 2025 am 11:37 AM

膠囊是一種三維幾何圖形,由一個圓柱體和兩端各一個半球體組成。膠囊的體積可以通過將圓柱體的體積和兩端半球體的體積相加來計算。本教程將討論如何使用不同的方法在Java中計算給定膠囊的體積。 膠囊體積公式 膠囊體積的公式如下: 膠囊體積 = 圓柱體體積 兩個半球體體積 其中, r: 半球體的半徑。 h: 圓柱體的高度(不包括半球體)。 例子 1 輸入 半徑 = 5 單位 高度 = 10 單位 輸出 體積 = 1570.8 立方單位 解釋 使用公式計算體積: 體積 = π × r2 × h (4

C語言多線程編程:新手指南與疑難解答 C語言多線程編程:新手指南與疑難解答 Apr 04, 2025 am 10:15 AM

C語言多線程編程指南:創建線程:使用pthread_create()函數,指定線程ID、屬性和線程函數。線程同步:通過互斥鎖、信號量和條件變量防止數據競爭。實戰案例:使用多線程計算斐波那契數,將任務分配給多個線程並同步結果。疑難解答:解決程序崩潰、線程停止響應和性能瓶頸等問題。

PHP與Python:核心功能 PHP與Python:核心功能 Apr 13, 2025 am 12:16 AM

PHP和Python各有優勢,適合不同場景。 1.PHP適用於web開發,提供內置web服務器和豐富函數庫。 2.Python適合數據科學和機器學習,語法簡潔且有強大標準庫。選擇時應根據項目需求決定。

PHP與其他語言:比較 PHP與其他語言:比較 Apr 13, 2025 am 12:19 AM

PHP適合web開發,特別是在快速開發和處理動態內容方面表現出色,但不擅長數據科學和企業級應用。與Python相比,PHP在web開發中更具優勢,但在數據科學領域不如Python;與Java相比,PHP在企業級應用中表現較差,但在web開發中更靈活;與JavaScript相比,PHP在後端開發中更簡潔,但在前端開發中不如JavaScript。

See all articles