日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

深入解析J.U.C并发包(十五)—— Thread - Specific Storage(ThreadLocal)模式

發(fā)布時(shí)間:2023/12/16 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入解析J.U.C并发包(十五)—— Thread - Specific Storage(ThreadLocal)模式 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、定義

Thread - Specific Storage就是“線程獨(dú)有的存儲(chǔ)庫”,該模式會(huì)對(duì)每個(gè)線程提供獨(dú)有的內(nèi)存空間。

java.lang.ThreadLocal類提供了該模式的實(shí)現(xiàn),ThreadLocal的實(shí)例是一種集合(collection)架構(gòu),該實(shí)例管理了很多對(duì)象,可以想象成一個(gè)保管有大量保險(xiǎn)箱的房間。

java.lang.ThreadLocal類的方法:

  • public void set()

該方法會(huì)檢查當(dāng)前調(diào)用線程,默認(rèn)以該線程的Thread.currentThread()值作為鍵,來保存指定的值。

  • public Object get()

該方法會(huì)檢查當(dāng)前調(diào)用線程,默認(rèn)以該線程的Thread.currentThread()值作為鍵,獲取保存指定的值。

二、模式案例

TSLog類:

package Entity;import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; // 實(shí)際執(zhí)行記錄日志的類,每個(gè)線程都會(huì)擁有一個(gè)該類的實(shí)例 public class TSLog {private PrintWriter writer = null;public TSLog(String fileName) {try {writer = new PrintWriter(new FileWriter(fileName));} catch (IOException e) {e.printStackTrace();}}public void println(String e) {writer.println(e);}public void close() {writer.println("****** End of log");writer.close();} }

Log類:

package Entity;public class Log {private static final ThreadLocal<TSLog> TS_LOG_THREAD_LOCAL = new ThreadLocal<>();public static void println(String s) {getTSLog().println(s);}public static void close() {getTSLog().close();}private static TSLog getTSLog() {TSLog tsLog = TS_LOG_THREAD_LOCAL.get();if (tsLog == null) {tsLog = new TSLog(Thread.currentThread() + "-log.txt");TS_LOG_THREAD_LOCAL.set(tsLog);}return tsLog;} }

ClientThread類:

package Entity;public class ClientThread extends Thread{public ClientThread(String name) {super(name);}@Overridepublic void run() {System.out.println(getName() + " BEGIN");for (int i = 0; i < 10; i++) {Log.println("i=" + i);try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}Log.close();System.out.println(getName() + " END");} }

main類:

import Entity.ClientThread;public class Demo2 {public static void main(String[] args) {new ClientThread("Alice").start();new ClientThread("Bobby").start();new ClientThread("Chris").start();} }

?

三、模式講解

Thread-Specific Storage模式的角色如下:

  • Client(委托人)參與者

Client參與者會(huì)將工作委托給TSObjectProxy參與者。(案例中的ClientThread類就是Client)

  • TSObjectProxy(線程獨(dú)有對(duì)象的代理者)參與者

TSObjectProxy參與者會(huì)處理多個(gè)Client委托的工作。(案例中的Log類就是TSObjectProxy)

  • TSObjectCollection(線程獨(dú)有對(duì)象的集合)參與者

(案例中的java.lang.ThreadLocal類就是TSObjectCollection)

  • TSObject(線程獨(dú)有的對(duì)象)參與者

TSObject存放線程所特有的信息,TSObject實(shí)例的方法只會(huì)由單線程調(diào)用,由TSObjectCollection管理,每個(gè)線程獨(dú)都擁有獨(dú)自的TSObject實(shí)例。(案例中的TSLog類就是TSObject)

四、ThreadLocal的原理

ThreadLocal類主要有四個(gè)方法:

1、初始化返回值的方法:

該方法實(shí)現(xiàn)只返回null,并且修飾符為protected,很明顯,如果用戶想返回初始值不為null,則需要重寫該方法;

protected T initialValue() {return null;}

2、get方法,獲取線程本地副本變量

public T get() {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null) {ThreadLocalMap.Entry e = map.getEntry(this);if (e != null) {@SuppressWarnings("unchecked")T result = (T)e.value;return result;}}return setInitialValue();}

3、set方法,設(shè)置線程本地副本變量

public void set(T value) {Thread t = Thread.currentThread();ThreadLocalMap map = getMap(t);if (map != null)map.set(this, value);elsecreateMap(t, value);}

4、remove方法,移除線程本地副本變量

public void remove() {ThreadLocalMap m = getMap(Thread.currentThread());if (m != null)m.remove(this);}

如果需要我們自己來設(shè)計(jì)ThreadLocal對(duì)象,那么,一般的實(shí)現(xiàn)思路:

設(shè)計(jì)一個(gè)線程安全的Map,key就是當(dāng)前線程對(duì)象,Value就是線程本地變量的值。

然而,JDK的實(shí)現(xiàn)思路:

讓每個(gè)Thread對(duì)象,自身持有一個(gè)Map,這個(gè)Map的Key就是當(dāng)前ThreadLocal對(duì)象,Value是本地線程變量值。相對(duì)于加鎖的實(shí)現(xiàn)方式,這樣做可以提升性能,其實(shí)是一種以空間換時(shí)間的思路。

ThreadLocal類有一個(gè)getMap()方法,其實(shí)就是返回Thread對(duì)象自身的Map——threadLocals。

ThreadLocalMap getMap(Thread t) {return t.threadLocals;}

threadLocals是一種ThreadLocal.ThreadLocalMap類型的數(shù)據(jù)結(jié)構(gòu),作為內(nèi)部類定義在ThreadLocal類中,其內(nèi)部采用一種WeakReference的方式保存鍵值對(duì)。

總結(jié)

以上是生活随笔為你收集整理的深入解析J.U.C并发包(十五)—— Thread - Specific Storage(ThreadLocal)模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。