The Thread-Specific Storage 線程保險箱
官方解釋
This class provides thread-local variables. These variables differ from their normal counterparts in that each thread that accesses one (via its get or set method) has its own, independently initialized copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).
該類提供線程局部變量。這些變量與普通的對應變量不同,因為每個訪問一個變量的線程(通過其get或set方法)都有自己獨立初始化的變量副本。ThreadLocal實例通常是希望將狀態與線程(例如,用戶ID或事務ID)關聯的類中的私有靜態字段。
ThreadLocal的初始化設定值和set設置值
package com.dwz.concurrency.chapter33; public class ThreadLocalSimpleTest { private static ThreadLocal<String> threadlocal = new ThreadLocal<String>() { @Override protected String initialValue() { return "dandan"; }; }; public static void main(String[] args) throws InterruptedException { threadlocal.set("Alex"); Thread.sleep(1000); System.out.println(threadlocal.get()); } }
模擬ThreadLocal的獨立性
package com.dwz.concurrency.chapter33; import java.util.Random; public class ThreadLocalComplexTest { private final static ThreadLocal<String> threadlocal = new ThreadLocal<>(); private final static Random random = new Random(System.currentTimeMillis()); public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(()->{ threadlocal.set("T1"); try { Thread.sleep(random.nextInt(1000)); System.out.println(Thread.currentThread().getName() + "&&" + threadlocal.get()); } catch (InterruptedException e) { e.printStackTrace(); } }); Thread t2 = new Thread(()->{ threadlocal.set("T2"); try { Thread.sleep(random.nextInt(1000)); System.out.println(Thread.currentThread().getName() + "&&" + threadlocal.get()); } catch (InterruptedException e) { e.printStackTrace(); } }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("=========================="); System.out.println(Thread.currentThread().getName() + "&&" + threadlocal.get()); } }
模擬線程保險箱
package com.dwz.concurrency.chapter33; import java.util.HashMap; import java.util.Map; /** * The Thread-Specific Storage 模擬線程保險箱 * 始終以當前線程作為key值 * @param <T> */ public class ThreadLocalSimulator<T> { private final Map<Thread, T> storage = new HashMap<>(); public void set(T t) { synchronized (this) { Thread key = Thread.currentThread(); storage.put(key, t); } } public T get() { synchronized (this) { Thread key = Thread.currentThread(); T value = storage.get(key); if(null == value) { return initialValue(); } return value; } } public T initialValue() { return null; } }
測試自定義線程保險箱
package com.dwz.concurrency.chapter33; import java.util.Random; public class ThreadLocalSimulatorTest { private final static ThreadLocalSimulator<String> threadlocal = new ThreadLocalSimulator<String>() { @Override public String initialValue() { return "No value"; }; }; //seed private final static Random random = new Random(System.currentTimeMillis()); public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(()->{ threadlocal.set("T1"); try { Thread.sleep(random.nextInt(1000)); System.out.println(Thread.currentThread().getName() + "&&" + threadlocal.get()); } catch (InterruptedException e) { e.printStackTrace(); } }); Thread t2 = new Thread(()->{ threadlocal.set("T2"); try { Thread.sleep(random.nextInt(1000)); System.out.println(Thread.currentThread().getName() + "&&" + threadlocal.get()); } catch (InterruptedException e) { e.printStackTrace(); } }); t1.start(); t2.start(); t1.join(); t2.join(); System.out.println("=========================="); System.out.println(Thread.currentThread().getName() + "&&" + threadlocal.get()); } }