生活随笔
收集整理的這篇文章主要介紹了
线程管理(九)使用本地线程变量
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
聲明:本文是《?Java 7 Concurrency Cookbook?》的第一章, 作者: Javier Fernández González 譯者:鄭玉婷 校對:方騰飛
使用本地線程變量
并發應用的一個關鍵地方就是共享數據。這個對那些擴展Thread類或者實現Runnable接口的對象特別重要。
如果你創建一個類對象,實現Runnable接口,然后多個Thread對象使用同樣的Runnable對象,全部的線程都共享同樣的屬性。這意味著,如果你在一個線程里改變一個屬性,全部的線程都會受到這個改變的影響。
有時,你希望程序里的各個線程的屬性不會被共享。 Java 并發 API提供了一個很清楚的機制叫本地線程變量。
在這個指南中, 我們將開發一個程序,這個程序用來描述在第一段話里的問題,和另一個程序使用本地線程變量機制解決這個問題。
準備
指南中的例子是使用Eclipse IDE 來實現的。如果你使用Eclipse 或者其他的IDE,例如NetBeans, 打開并創建一個新的java項目。
怎么做呢…
按照這些步驟來實現下面的例子:
1.? ?首先,我們來實現一個程序含有上述的問題。
創建一個類名為 UnsafeTask 并實現 Runnable 接口。 聲明一個?private?java.util.Date 屬性.
| 1 | public?class?UnsafeTask?implements?Runnable{ |
| 2 | private?Date startDate; |
2. 實現UnsafeTask 對象的run() 方法,此方法會初始 startDate 屬性, 把值寫入控制臺,隨機休眠一段時間,最后在寫入startDate 屬性。
| 04 | System.out.printf("Starting Thread: %s : %s\n",Thread. currentThread().getId(),startDate); |
| 06 | TimeUnit.SECONDS.sleep( (int)Math.rint(Math.random()*10)); |
| 07 | }?catch?(InterruptedException e) { |
| 10 | System.out.printf("Thread Finished: %s : %s\n",Thread. currentThread().getId(),startDate); |
3.? ?現在,來實現這個有問題例子的主類。創建一個 Main ?類和 main() 方法. 此方法會創建一個 UnsafeTask 類的對象,并開始3個線程使用這個對象,每個線程間休眠2秒。
| 02 | public?static?void?main(String[] args) { |
| 03 | UnsafeTask task=new?UnsafeTask(); |
| 04 | ?for?(int?i=0; i<10; i++){ |
| 05 | Thread thread=new?Thread(task); |
| 07 | try?{ TimeUnit.SECONDS.sleep(2); |
| 08 | }?catch?(InterruptedException e) { |
4.? ?在以下的裁圖,你可以發現這個程序的執行結果。每個線程有著不同的開始時間,但是全部都有相同的結束時間。
5.? ?如在之前提到的, 我們會使用本地線程變量機制來解決這個問題。
6.? ?創建一個類名為 SafeTask a一定實現 Runnable 接口。
| 1 | public?class?SafeTask?implements?Runnable { |
7.?? 聲明 ThreadLocal<Date> 類對象。此對象有隱含實現了 initialValue()方法. 此方法會返回真實日期。
| 1 | private?static?ThreadLocal<Date> startDate=?new?ThreadLocal<Date>() { |
| 2 | protected?Date initialValue(){ |
8.? ?實現run()方法。它和 UnsafeClass的run() 方法功能一樣,只是改變了屬性的訪問方式。
| 03 | ??System.out.printf("Starting Thread: %s : %s\n",Thread.currentThread().getId(),startDate.get()); |
| 05 | ??TimeUnit.SECONDS.sleep((int)Math.rint(Math.random()*10)); |
| 06 | }?catch?(InterruptedException e) { |
| 09 | System.out.printf("Thread Finished: %s : %s\n",Thread.currentThread().getId(),startDate.get()); |
9. ???這個例子的主類跟不安全例子一樣,把名字改成 Runnable 類。
10. 運行例子并分析不同處。
它是怎么工作的…
在下面的截圖里,你可以看到線程安全模式下程序運行的結果。現在3個 Thread 對象都有他們自己的startDate 屬性值。看下圖:
本地線程變量為每個使用這些變量的線程儲存屬性值。可以用 get() 方法讀取值和使用 set() 方法改變值。 如果第一次你訪問本地線程變量的值,如果沒有值給當前的線程對象,那么本地線程變量會調用 initialValue() 方法來設置值給線程并返回初始值。
更多…
本地線程類還提供 remove() 方法,刪除存儲在線程本地變量里的值。
Java 并發 API 包括 InheritableThreadLocal 類提供線程創建線程的值的遺傳性 。如果線程A有一個本地線程變量,然后它創建了另一個線程B,那么線程B將有與A相同的本地線程變量值。 你可以覆蓋 childValue() 方法來初始子線程的本地線程變量的值。 它接收父線程的本地線程變量作為參數。
原創文章,轉載請注明:?轉載自并發編程網 – ifeve.com本文鏈接地址:?線程管理(九)使用本地線程變量
文章轉自?并發編程網-ifeve.com
總結
以上是生活随笔為你收集整理的线程管理(九)使用本地线程变量的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。