




下載本文檔
版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、簡單分析java線程編程中threadlocal類的使用這篇文章主要介紹了 java線程編程屮threadlocal類的使用,包括使用其對共享變量的操作的 分析,需要的朋友可以參考下一、概述threadlocal是什么呢?其實threadlocal并非是一個線程的本地實現版本,它并不是一個 thread,而是threadlocalvariable(線程局部變量)。也許把它命名為threadlocalvar更加合適。 線程局部變量仃hreadlocal)其實的功用非常簡單,就是為每一個使用該變量的線程都提供一 個變量值的副本,是java中一種較為特殊的線程綁定機制,是每一個線程都可以獨立地改 變
2、自己的副本,而不會和其它線程的副本沖突。從線程的角度看,每個線程都保持一個對其線程局部變量副本的隱式引用,只要線程是活 動的并且threadlocal實例是可訪問的;在線程消失之后,其線程局部實例的所有副本都會 被垃圾回收(除非存在對這些副本的其他引用)。通過threadlocal存取的數據,總是與當前線程相關,也就是說,jvm為每個運行的線程, 綁定了私有的本地實例存取空間,從而為多線程環境常出現的并發訪問問題提供了一種隔離 機制。threadlocal是如何做到為每一個線程維護變量的副本的呢?其實實現的思路很簡單,在 threadlocal類屮有一個map,用于存儲每一個線程的變量的副本。
3、概括起來說,對于多線程資源共享的問題,同步機制采用了 “以時間換空間”的方式,而 threadlocal釆用了 “以空間換時間”的方式。前者僅提供一份變量,讓不同的線程排隊訪 問,而后者為每一個線程都提供了一份變量,因此可以同時訪問而互不影響。二、api說明threadlocal()創建一個線程本地變量。t get()返回此線程局部變量的當前線程副本中的值,如果這是線程第一次調用該方法, 則創建并初始化此副本。protected t initialvalue()返回此線程局部變量的當前線程的初始值。最多在每次訪問線程來獲得每個線 程局部變量時調用此方法一次,即線程第一次使用get()方法訪問變
4、量的時候。如果線程先 于get方法調用set(t)方法,貝!i不會在線程中再調用initialvalue方法。若該實現只返回null;如果程序員希望將線程局部變量初始化為null以外的某個值, 則必須為threadlocal創建子類,并重寫此方法。通常,將使用匿名內部類q initialvalue的 典型實現將調用一個適當的構造方法,并返回新構造的對象。void remove()移除此線程局部變量的值。這可能有助于減少線程局部變量的存儲需求。如果 再次訪問此線程局部變量,那么在默認情況下它將擁有其initialvalue-void set(t value)將此線程局部變量的當前線程副本中的值設
5、置為指定值。許多應用程序不需要 這項功能,它們只依賴于initialvaluef)方法來設置線程局部變量的值。在程序中一般都重寫initialvalue方法,以給定一個特定的初始值。三、一.對threadlocal的理解threadlocal,很多地方叫做線程本地變量,也有些地方叫做線程本地存儲,其實意思差 不多。可能很多朋友都知道threadlocal為變量在每個線程中都創建了一個副本,那么每個 線程可以訪問自己內部的副本變量。這句話從字面上看起來很容易理解,但是真止理解并不是那么容易。我們還是先來看一個例子:public staticconn ect =publicclass conn e
6、cti onman ager private static conn ection conn ect = n ull;conn ection openc onn ection() 訐(connect = null)drivermgetconnectionf); return connect; static void closeconnection() 訐(connect!=null)connect.close(); 假設有這樣一個數據庫鏈接管理類,這段代碼在單線程中使用是沒有任何問題的,但 是如果在多線程屮使用呢?很顯然,在多線程屮使用會存在線程安全問題:第一,這里面的 2個方法都沒有進行同步
7、,很可能在openconnection方法中會多次創建connect;第二,由 于connect是共亨變量,那么必然在調用connect的地方需要使用到同步來保障線程安全, 因為很可能一個線程在使用connect進行數據庫操作,而另外一個線程調用closeconnection 關閉鏈接。所以出于線程安全的考慮,必須將這段代碼的兩個方法進行同步處理,并且在調用 connect的地方需要進彳亍同步處理。這樣將會大大影響程序執行效率,因為一個線程在使用connect進行數據庫操作的時候, 其他線程只有等待。那么大家來仔細分析一下這個問題,這地方到底需不需要將connect變量進行共亨?事 實上,是不
8、需要的。假如每個線程屮都有一個connect變量,各個線程之間對connect變量的訪問實際上是沒有依賴關系的,即一個線程不需要關心其他線程是否對這個connect進行 了修改的。到這里,對能會有朋友想到,既然不需要在線程之間共享這個變量,可以直接這樣處理, 在每個需要使用數據庫連接的方法中具體使用時才創建數據庫鏈接,然后在方法調用完畢再 釋放這個連接。比如下面這樣:class connectionmanager ope nconn ection() driverma nager.getc onn ection();private connection connect = null; if(c
9、onn ect =n ull)return conn ect; public connection conn ect = public voidcloseconnection() if(connect!二null)connect.close(); class dao public voidin sert() conn ecti onman ager conn ecti onman ager = new conn ecti onman ager();conn ection conn ecti on = conn ectionmanager.ope nconn ection();/使用 conn
10、ection進彳亍操作conn ectio nman ager.closec onn ectio n(); 這樣處理確實也沒有任何問題,由于每次都是在方法內部創建的連接,那么線程之間 自然不存在線程安全問題。但是這樣會有一個致命的影響:導致服務器壓力非常人,并且嚴 重影響程序執行性能。由于在方法中需要頻繁地開啟和關閉數據庫連接,這樣不盡嚴重影響 程序執行效率,還可能導致服務器壓力巨大。那么這種情況下使用threadlocal是再適合不過的了,因為th read local在每個線程屮對 該變量會創建一個副本,即每個線程內部都會有一個該變量,且在線程內部任何地方都可以 使用,線程之間互不影響,這
11、樣一來就不存在線程安全問題,也不會嚴重影響程序執行性能。但是要注意,雖然threadlocal能夠解決上面說的問題,但是由于在每個線程中都創建 了副本,所以要考慮它對資源的消耗,比如內存的占用會比不使用threadlocal要大。四、實例創建一個bean,通過不同的線程對象設置bean屬性,保證各個線程bean對象的獨立性。/* * created by intellij idea. * user: leizhimin * date: 2007-11-23 * time: 10:45:02 * 學生 */public class student private int age = 0; 年齡
12、public int getage() return this.age; public void setage(int age) this.age = age; /* * created by intellij idea. * user: leizhimin * date: 2007-11-23 * time: 10:53:33 * 多線程下測試程序 */public class threadlocaldemo implements runnable 創建線程局部變u: studentlocal,在后而你會發 現用來保存 student 對彖 private final static thre
13、adlocal studentlocal = new threadlocal(); public static void main(string agrs) threadlocaldemo td = new threadlocaldemo(); thread tl = new threadftd, "a"); thread t2 = new threaded, "b"); tl.start(); t2.start(); public void run() accessstudent(); /* 示例業務方法,用來測試 */ public void acc
14、essstudent() 獲取當前線程的名字 string currentthreadname=thread.curre ntthread()getname();system.out.println(currentthreadname + "is running!"); 產生一個隨機數并打印 random ran dom = new ran dom();int age = rand om.nextlnt(loo);system.out.println("thread " + currentthreadname + " set e to:&quo
15、t; + age); 獲取一個student對象,并將隨機數年齡插入到對象屬性中student student =getstudent();student.setage(age);system.out.println("thread " + currentthreadname +"first read age is:" + student.getage(); try thread.sleep(500); catch(interruptedexception ex) ex.printstacktrace(); system.out.println(&quo
16、t;thread " +currentthreadname + " second read age is:" + student.getage(); protected student getstudent() 獲取本地線程變量并強制轉換為student類型 student student =(student) studentlocal.getf); 線程首次執行此方法的吋候,studentlocal.get()肯定為 null if (student = null) 創建一個student對象,并保存到本地線程變量studentlocal屮 student =
17、new stude nt();stud en tlocal.set(student);return stud ent; 運行結果:a is running! thread a set age to:76 b is running! thread b set age to:27 thread a first read age is:76 thread b first read age is:27 thread a second read age is:76 thread b second read age is:27可以看到a、b兩個線程age在不同時刻打印的值是完全相同的。這個程序通過妙用 threadlocal,既實現多線程并發,游兼顧數據的安全性。五、thread
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 公司業績競賽活動方案
- 公司中秋午宴活動方案
- 公司中秋節員工活動方案
- 公司主持人活動方案
- 公司舉辦家庭活動方案
- 公司舉辦聯歡會活動方案
- 公司舉行沙龍活動方案
- 公司爭優創先活動方案
- 公司五一戶外活動方案
- 公司五四線上活動方案
- 2025屆河南省洛陽市等兩地高三下學期三模歷史試題(含答案)
- 智能口罩設計優化-洞察闡釋
- 2024年湖北省南漳縣事業單位公開招聘教師崗考試題帶答案分析
- 2025浙江寧波市余姚市市屬企業面向社會招聘企業員工68人筆試參考題庫附帶答案詳解
- 限高架維修合同8篇
- 2025年4月八大員-勞務員練習題庫與參考答案解析
- 2025-2030肺癌手術行業市場現狀供需分析及投資評估規劃分析研究報告
- 農村飲水安全工程可行性研究報告
- 一級注冊建筑師真題含答案2025年
- 全麻期間氣道梗阻的預防與處理
- 工業大數據的安全與隱私保護-洞察闡釋
評論
0/150
提交評論