1,ThreadLocal 不是「本地線程」的意思,而是Thread 的局部變量。每一個使用該變量的線程提供獨立的變量副本,因此每個線程均可以獨立地改變本身的副本,而不會影響其它線程所對應的副本安全
2,提供的接口方法this
• void set(Object value)設置當前線程的線程局部變量的值。spa
• public Object get()該方法返回當前線程所對應的線程局部變量。線程
• public void remove()將當前線程局部變量的值刪除,目的是爲了減小內存的佔用,該方法是JDK 5.0新增的方法。須要指出的是,當線程結束後,對應該線程的局部變量將自動被垃圾回收,因此顯式調用該方法清除線程的局部變量並非必須的操做,但它能夠加快內存回收的速度。設計
• protected Object initialValue()返回該線程局部變量的初始值,該方法是一個protected的方法,顯然是爲了讓子類覆蓋而設計的。這個方法是一個延遲調用方法,在線程第1次調用get()或set(Object)時才執行,而且僅執行1次。ThreadLocal中的缺省實現直接返回一個null。code
3,兩個線程共享資源的狀況blog
public class Res { public Integer count = 0; public Integer getNum() { return ++count; } }
public class CountThread implements Runnable { private Res res; public CountThread(Res res) { this.res = res; } public void run() { for (int i = 0; i < 3; i++) { System.out.println(Thread.currentThread().getName() + "----" + res.getNum()); } } }
public class App { public static void main(String[] args) { //共享資源; Res res = new Res(); CountThread countThread = new CountThread(res); Thread t1 = new Thread(countThread); Thread t2 = new Thread(countThread); t1.start(); t2.start(); } }
打印結果:線程不安全接口
Thread-0----1 Thread-1----1 Thread-0----2 Thread-0----4 Thread-1----3 Thread-1----5
使用ThreadLocal 讓每一個線程單獨擁有本身的局部變量內存
public class Res { public ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>(){ //每一個線程只會調用一次 protected Integer initialValue() { return 0; }; }; public Integer getNum() { int count = threadLocal.get() +1; threadLocal.set(count); return count; } }
打印結果:資源
Thread-0----1 Thread-0----2 Thread-1----1 Thread-1----2 Thread-1----3 Thread-0----3