生活随笔
收集整理的這篇文章主要介紹了
Java TheadLocal
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
原文鏈接?作者:Jakob Jenkov ??查看全部文章
Java中的ThreadLocal類可以讓你創(chuàng)建的變量只被同一個(gè)線程進(jìn)行讀和寫操作。因此,盡管有兩個(gè)線程同時(shí)執(zhí)行一段相同的代碼,而且這段代碼又有一個(gè)指向同一個(gè)ThreadLocal變量的引用,但是這兩個(gè)線程依然不能看到彼此的ThreadLocal變量域。
1、創(chuàng)建一個(gè)ThreadLocal對(duì)象
2、訪問ThreadLocal對(duì)象
3、ThreadLocal泛型
4、初始化ThreadLocal
5、Full ThreadLocal Example
6、InheritableThreadLocal
1、創(chuàng)建一個(gè)ThreadLocal對(duì)象
如下所示,創(chuàng)建一個(gè)ThreadLocal變量:
| 1 | private?ThreadLocal myThreadLocal =?new?ThreadLocal(); |
你實(shí)例化了一個(gè)ThreadLocal對(duì)象。每個(gè)線程僅需要實(shí)例化一次即可。雖然不同的線程執(zhí)行同一段代碼時(shí),訪問同一個(gè)ThreadLocal變量,但是每個(gè)線程只能看到私有的ThreadLocal實(shí)例。所以不同的線程在給ThreadLocal對(duì)象設(shè)置不同的值時(shí),他們也不能看到彼此的修改。
2、訪問ThreadLocal對(duì)象
一旦創(chuàng)建了一個(gè)ThreadLocal對(duì)象,你就可以通過以下方式來存儲(chǔ)此對(duì)象的值:
| 1 | myThreadLocal.set("A thread local value"); |
也可以直接讀取一個(gè)ThreadLocal對(duì)象的值:
| 1 | String threadLocalValue = (String) myThreadLocal.get(); |
get()方法會(huì)返回一個(gè)Object對(duì)象,而set()方法則依賴一個(gè)Object對(duì)象參數(shù)。
3、ThreadLocal泛型
為了使get()方法返回值不用做強(qiáng)制類型轉(zhuǎn)換,通常可以創(chuàng)建一個(gè)泛型化的ThreadLocal對(duì)象。以下就是一個(gè)泛型化的ThreadLocal示例:
| 1 | private?ThreadLocal myThreadLocal1 =?new?ThreadLocal<String>(); |
現(xiàn)在你可以存儲(chǔ)一個(gè)字符串到ThreadLocal實(shí)例里,此外,當(dāng)你從此ThreadLocal實(shí)例中獲取值的時(shí)候,就不必要做強(qiáng)制類型轉(zhuǎn)換。
| 1 | myThreadLocal1.set("Hello ThreadLocal"); |
| 2 | String threadLocalValues = myThreadLocal.get(); |
4、初始化ThreadLocal
由于ThreadLocal對(duì)象的set()方法設(shè)置的值只對(duì)當(dāng)前線程可見,那有什么方法可以為ThreadLocal對(duì)象設(shè)置的值對(duì)所有線程都可見。
為此,我們可以通過ThreadLocal子類的實(shí)現(xiàn),并覆寫initialValue()方法,就可以為ThreadLocal對(duì)象指定一個(gè)初始化值。如下所示:
| 1 | private?ThreadLocal myThreadLocal =?new?ThreadLocal<String>() { |
| 2 | ???@Override?protected?String initialValue() { |
| 3 | ???????return?"This is the initial value"; |
此時(shí),在set()方法調(diào)用前,當(dāng)調(diào)用get()方法的時(shí)候,所有線程都可以看到同一個(gè)初始化值。
5、Full ThreadLocal Example
以下是一個(gè)完整的ThreadLocal示例:
| 01 | public?class?ThreadLocalExample { |
| 03 | ????public?static?class?MyRunnable?implements?Runnable { |
| 05 | ????????private?ThreadLocal<Integer> threadLocal = |
| 06 | ???????????????new?ThreadLocal<Integer>(); |
| 09 | ????????public?void?run() { |
| 10 | ????????????threadLocal.set( (int) (Math.random() * 100D) ); |
| 13 | ????????????????Thread.sleep(2000); |
| 14 | ????????????}?catch?(InterruptedException e) { |
| 17 | ????????????System.out.println(threadLocal.get()); |
| 21 | ????public?static?void?main(String[] args) { |
| 22 | ????????MyRunnable sharedRunnableInstance =?new?MyRunnable(); |
| 24 | ????????Thread thread1 =?new?Thread(sharedRunnableInstance); |
| 25 | ????????Thread thread2 =?new?Thread(sharedRunnableInstance); |
| 27 | ????????thread1.start(); |
| 28 | ????????thread2.start(); |
| 30 | ????????thread1.join();?//wait for thread 1 to terminate |
| 31 | ????????thread2.join();?//wait for thread 2 to terminate |
上面創(chuàng)建了兩個(gè)線程共享一個(gè)MyRunnable實(shí)例。每個(gè)線程執(zhí)行run()方法的時(shí)候,會(huì)給同一個(gè)ThreadLocal實(shí)例設(shè)置不同的值。如果調(diào)用set()方法的時(shí)候用synchronized關(guān)鍵字同步,而且不是一個(gè)ThreadLocal對(duì)象實(shí)例,那么第二個(gè)線程將會(huì)覆蓋第一個(gè)線程所設(shè)置的值。
然而,由于是ThreadLocal對(duì)象,所以兩個(gè)線程無法看到彼此的值。因此,可以設(shè)置或者獲取不同的值。
6、InheritableThreadLocal
InheritableThreadLocal類是ThreadLocal的子類。為了解決ThreadLocal實(shí)例內(nèi)部每個(gè)線程都只能看到自己的私有值,所以InheritableThreadLocal允許一個(gè)線程創(chuàng)建的所有子線程訪問其父線程的值。
原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明:?轉(zhuǎn)載自并發(fā)編程網(wǎng) – ifeve.com本文鏈接地址:?《Java并發(fā)性和多線程介紹》-Java TheadLocal
總結(jié)
以上是生活随笔為你收集整理的Java TheadLocal的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。