ThreadLocal和synchronized都是爲了解決多線程中相同變量的訪問衝突問題。synchronized保證同一時刻只有一個線程對共享變量進行操做,synchronized是時間換空間的體現。ThreadLocal使變量在每一個線程中都有獨立拷貝的共享變量,不會出現一個線程讀取變量時而被另外一個線程修改的現象。ThreadLocal是編程中空間換時間的體現。java
一、每一個Thread線程內部都有一個Map。
二、Map裏面存儲線程本地對象(key)和線程的變量副本(value)。
三、每一個Thread線程內部都有一個Map。
四、Thread對於不一樣的線程,每次獲取副本值時,別的線程並不能獲取到當前線程的副本值,造成了副本的隔離,互不干擾。編程
從上圖能夠看到每一個線程,ThreadLocal內部都有一個Map來存儲當前線程的共享變量,只能當前線程訪問,從而保證不會影響其餘線程的變量。多線程
get()方法用於獲取當前線程的副本變量值。
set()方法用於保存當前線程的副本變量值。
initialValue()爲當前線程初始副本變量值。
remove()方法移除當前前程的副本變量值。併發
//包含業務惟一標識的類 public class Context { private String transactionId; public String getTransactionId() { return transactionId; } public void setTransactionId(String transactionId) { this.transactionId = transactionId; } } // 其中引用了Context類 public class MyThreadLocal { private static final ThreadLocal<Context> userThreadLocal = new ThreadLocal<Context>(); public static void set(Context user){ userThreadLocal.set(user); } public static void unset(){ userThreadLocal.remove(); } public static Context get(){ return userThreadLocal.get(); } } //ThreadLocalDemo.java。生成並將業務標識設置到ThreadLocal中而後在業務方法中調用 public class ThreadLocalDemo implements Runnable{ private static AtomicInteger ai = new AtomicInteger(0); public void run() { Context context = new Context(); context.setTransactionId(getName()); //設置線程變量 MyThreadLocal.set(context); System.out.println("request["+Thread.currentThread().getName()+"]:"+context.getTransactionId()); new BusinessService().businessMethod(); MyThreadLocal.unset(); } private String getName() { return ai.getAndIncrement()+""; } public static void main(String[] args) { ThreadLocalDemo tld = new ThreadLocalDemo(); new Thread(tld).start(); new Thread(tld).start(); } } public class BusinessService { public void businessMethod() { Context context = MyThreadLocal.get(); System.out.println("service["+Thread.currentThread().getName()+"]:"+context.getTransactionId()); } }
一、每一個ThreadLocal只能保存一個變量副本,若是想要上線一個線程可以保存多個副本以上,就須要建立多個ThreadLocal。
二、ThreadLocal內部的ThreadLocalMap鍵爲弱引用,會有內存泄漏的風險。
三、ThreadLocal適用於無狀態,副本變量獨立後不影響業務邏輯的高併發場景。若是若是業務邏輯強依賴於副本變量,則不適合用ThreadLocal解決,須要另尋解決方案。高併發
若是內容對你有幫助但願點贊收藏謝謝!!!this