目标:用于每个线程资源的隔离.
当工作于多线程中的对象使用ThreadLocal 维护变量时,ThreadLocal 为 每个使用该变量的线程分配一个独立的变量副本,
threadLocal 原理与使用
。每个线程独立改变自己的副本,而不影响其他线程所对应的变量副本。不同于线程同步:线程同步用于解决一个变量同一时刻被多个线程共享的问题(共享一个变量)。
threadLocal 使得一个变量在多个线程中各自拥有自己的副本(实现资源的隔离)。
原理:
ThreadLocal 中有一个map, 用于存储每一个线程的变量副本,其中map的key为 线程对象,value为对应线程的变量副本。
<code class="hljs cs">public class SimpleThreadLocal<t>{ private Map valueMap = Collections.synchronizedMap(new HashMap()); public void set(T value) { valueMap.put(Thread.currentThread(), value); } public T get() { Thread currentThread = Thread.currentThread(); T value = (T) valueMap.get(currentThread); if(value == null && !valueMap.containsKey(currentThread)) { value = initValue(); valueMap.put(currentThread, value); } return value; } public void remove() { valueMap.remove(Thread.currentThread()); } public T initValue() { return null; }}</t></code>
应用场景:
web应用分层结构中:同一变量在持久化,业务,展示层传递时(同一线程)。
接口方法:
<code class="hljs cs">protected T initialValue(); //return the initial value for this thread-local public T get(); //return the current thread's value of this thread-local public void set(T value); //@param value the value to be stored in the current thread's copy of this thread-local. public void remove(); //Removes the current thread's value for this thread-local variable.</code>
示例:
<code class="hljs cs">ThreadLocalContext.classpublic class ThreadLocalContext { private static ThreadLocal<integer>threadLocalNum = new ThreadLocal<integer>() { @Override protected Integer initialValue() { return 0; } }; public int getNextNum() { threadLocalNum.set(threadLocalNum.get()+1); return threadLocalNum.get(); }}</integer></integer></code>
<code class="hljs axapta">ThreadLocalTest.classpublic class ThreadLocalTest { public static void main(String[] args) { ThreadLocalContext threadLocalContext = new ThreadLocalContext(); WorkThread workThread1 = new WorkThread(threadLocalContext); WorkThread workThread2 = new WorkThread(threadLocalContext); WorkThread workThread3 = new WorkThread(threadLocalContext); workThread1.start(); workThread2.start(); workThread3.start(); }}class WorkThread extends Thread{ private ThreadLocalContext threadLocalContext; public WorkThread(ThreadLocalContext threadLocalContext) { this.threadLocalContext = threadLocalContext; } public void run() { for(int i = 0; i < 5; i++) { System.out.println("thread[" + Thread.currentThread().getName() + "] threadLocalNum [" + threadLocalContext.getNextNum() + "]"); } }}</code>