摘要:案例中的類就是線程獨有對象的代理者參與者參與者會處理多個委托的工作。然而,的實現思路讓每個對象,自身持有一個,這個的就是當前對象,是本地線程變量值。
一、定義
Thread-Specific Storage就是“線程獨有的存儲庫”,該模式會對每個線程提供獨有的內存空間。
java.lang.ThreadLocal類提供了該模式的實現,ThreadLocal的實例是一種集合(collection)架構,該實例管理了很多對象,可以想象成一個保管有大量保險箱的房間。
java.lang.ThreadLocal類的方法:
public void set()
該方法會檢查當前調用線程,默認以該線程的Thread.currentThread()值作為鍵,來保存指定的值。
public Object get()
該方法會檢查當前調用線程,默認以該線程的Thread.currentThread()值作為鍵,獲取保存指定的值。
二、模式案例TSLog類:
//實際執行記錄日志的類,每個線程都會擁有一個該類的實例 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 s) { writer.println(s); } public void close() { writer.println("==== End of log ===="); writer.close(); } }
Log類:
public class Log { private static final ThreadLocaltsLogCollection = new ThreadLocal (); public static void println(String s) { getTSLog().println(s); } public static void close() { getTSLog().close(); } private static TSLog getTSLog() { TSLog tsLog = (TSLog) tsLogCollection.get(); if (tsLog == null) { tsLog = new TSLog(Thread.currentThread().getName() + "-log.txt"); tsLogCollection.set(tsLog); } return tsLog; } }
ClientThread類:
public class ClientThread extends Thread { public ClientThread(String name) { super(name); } public 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) { } } Log.close(); System.out.println(getName() + " END"); } }
執行:
Alice、Bobby、Chris三個線程調用Log類的同一個方法,但實際上每個線程都擁有獨自的TSLog實例。
public class Main { public static void main(String[] args) { new ClientThread("Alice").start(); new ClientThread("Bobby").start(); new ClientThread("Chris").start(); } }三、模式講解
Thread-Specific Storage模式的角色如下:
Client(委托人)參與者
Client參與者會將工作委托給TSObjectProxy參與者。(案例中的ClientThread類就是Client)
TSObjectProxy(線程獨有對象的代理者)參與者
TSObjectProxy參與者會處理多個Client委托的工作。(案例中的Log類就是TSObjectProxy)
TSObjectCollection(線程獨有對象的集合)參與者
(案例中的java.lang.ThreadLocal類就是TSObjectCollection)
TSObject(線程獨有的對象)參與者
TSObject存放線程所特有的信息,TSObject實例的方法只會由單線程調用,由TSObjectCollection管理,每個線程都擁有獨立的TSObject實例。(案例中的TSLog類就是TSObject)
四、ThreadLocal的原理ThreadLocal類主要有四個方法:
1、初始化返回值的方法:
該方法實現只返回 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) { T result = (T)e.value; return result; } } return setInitialValue(); }
3、set方法,設置線程本地副本變量
public void set(T value) { Thread t = Thread.currentThread(); ThreadLocalMap map = getMap(t); if (map != null) map.set(this, value); else createMap(t, value); }
4、remove方法,移除線程本地副本變量
public void remove() { ThreadLocalMap m = getMap(Thread.currentThread()); if (m != null) m.remove(this); }
如果需要我們自己來設計ThreadLocal對象,那么,一般的實現思路:
設計一個線程安全的Map,key就是當前線程對象,Value就是線程本地變量的值。
然而,JDK的實現思路:
讓每個Thread對象,自身持有一個Map,這個Map的Key就是當前ThreadLocal對象,Value是本地線程變量值。相對于加鎖的實現方式,這樣做可以提升性能,其實是一種以時間換空間的思路。
ThreadLocal類有個getMap()方法,其實就是返回Thread對象自身的Map——threadLocals。
ThreadLocalMap getMap(Thread t) { return t.threadLocals; }
threadLocals是一種ThreadLocal.ThreadLocalMap類型的數據結構,作為內部類定義在ThreadLocal類中,其內部采用一種WeakReference的方式保存鍵值對。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/71507.html
摘要:具體怎么實現的呢,思想其實特別簡單,我們在深入理解中的變量上一文的最后有提起過,就是創建一個全局字典,然后將線程或者協程標識符作為,相應線程或協程的局部數據作為。 在上篇我們看到了 ThreadLocal 變量的簡單使用,中篇對python中 ThreadLocal 的實現進行了分析,但故事還沒有結束。本篇我們一起來看下Werkzeug中ThreadLocal的設計。 Werkzeug...
摘要:并發設計模式一模式的使用表示線程本地存儲模式。為不同的任務創建不同的線程池,這樣能夠有效的避免死鎖問題。兩階段終止,即將線程的結束分為了兩個階段,第一個階段是一個線程向另一個線程發送終止指令,第二個階段是線程響應終止指令。 Java 并發設計模式 一、Thread Local Storage 模式 1. ThreadLocal 的使用 Thread Local Storage 表示線程...
摘要:并沒有提供語言級的線程局部變量,而是在類庫里提供了線程局部變量的功能,也就是這次的主角類。 Yuicon 轉載請注明原創出處,謝謝! 序 在多線程環境下,訪問非線程安全的變量時必須進行線程同步,例如使用synchronized方式訪問HashMap實例。但是同步訪問會降低并發性,影響系統性能。這時候就可以用空間換時間,如果我們給每個線程都分配一個獨立的變量,就可以用非同步的方式使用非...
摘要:基本在項目開發中基本不會用到但是面試官是比較喜歡問這類問題的所以還是有必要了解一下該類的功能與原理的是什么是一個將在多線程中為每一個線程創建單獨的變量副本的類當使用來維護變量時會為每個線程創建單獨的變量副本避免因多線程操作共享變量而導致的數 ThreadLocal基本在項目開發中基本不會用到, 但是面試官是比較喜歡問這類問題的;所以還是有必要了解一下該類的功能與原理的. Thread...
摘要:我們知道多線程環境下,每一個線程均可以使用所屬進程的全局變量。在線程中使用局部變量則不存在這個問題,因為每個線程的局部變量不能被其他線程訪問。 我們知道多線程環境下,每一個線程均可以使用所屬進程的全局變量。如果一個線程對全局變量進行了修改,將會影響到其他所有的線程。為了避免多個線程同時對變量進行修改,引入了線程同步機制,通過互斥鎖,條件變量或者讀寫鎖來控制對全局變量的訪問。 只用全局變...
閱讀 3667·2023-04-26 02:07
閱讀 3172·2021-09-22 15:55
閱讀 2544·2021-07-26 23:38
閱讀 3124·2019-08-29 15:16
閱讀 2017·2019-08-29 11:16
閱讀 1758·2019-08-29 11:00
閱讀 3596·2019-08-26 18:36
閱讀 3169·2019-08-26 13:32