ThreadLocal使用详解
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()); } }