目標(biāo):用于每個(gè)線程資源的隔離.
當(dāng)工作于多線程中的對象使用ThreadLocal 維護(hù)變量時(shí),ThreadLocal 為 每個(gè)使用該變量的線程分配一個(gè)獨(dú)立的變量副本,
threadLocal 原理與使用
。每個(gè)線程獨(dú)立改變自己的副本,而不影響其他線程所對應(yīng)的變量副本。不同于線程同步:線程同步用于解決一個(gè)變量同一時(shí)刻被多個(gè)線程共享的問題(共享一個(gè)變量)。
threadLocal 使得一個(gè)變量在多個(gè)線程中各自擁有自己的副本(實(shí)現(xiàn)資源的隔離)。
原理:
ThreadLocal 中有一個(gè)map, 用于存儲每一個(gè)線程的變量副本,其中map的key為 線程對象,value為對應(yīng)線程的變量副本。
<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>
應(yīng)用場景:
web應(yīng)用分層結(jié)構(gòu)中:同一變量在持久化,業(yè)務(wù),展示層傳遞時(shí)(同一線程)。
接口方法:
<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>