Java的ThreadLocal變量用來建立線程本地變量。咱們知道,一個對象上的全部線程,都會共享該對象的變量,因此這些共享的變量不是線程安全的。咱們能夠使用synchronization同步語法來使得線程安全,但若是想避免使用synchronization,那麼能夠使用線程本地變量(ThreadLocal variables)。java
使用了ThreadLocal變量後,每一個線程都有它本身的本地變量,能夠經過get()、set()方法來得到或設置這些變量的值。ThreadLocal實例一般是類中想要將狀態與線程關聯的私有靜態字段。安全
下面經過一段代碼來認識ThreadLocal:dom
package com.journaldev.threads; import java.text.SimpleDateFormat; import java.util.Random; public class ThreadLocalExample implements Runnable{ // SimpleDateFormat is not thread-safe, so give one to each thread private static final ThreadLocal<SimpleDateFormat> formatter = new ThreadLocal<SimpleDateFormat>(){ @Override protected SimpleDateFormat initialValue() { return new SimpleDateFormat("yyyyMMdd HHmm"); } }; public static void main(String[] args) throws InterruptedException { ThreadLocalExample obj = new ThreadLocalExample(); for(int i=0 ; i<10; i++){ Thread t = new Thread(obj, ""+i); Thread.sleep(new Random().nextInt(1000)); t.start(); } } @Override public void run() { System.out.println("Thread Name= "+Thread.currentThread().getName()+" default Formatter = "+formatter.get().toPattern()); try { Thread.sleep(new Random().nextInt(1000)); } catch (InterruptedException e) { e.printStackTrace(); } //formatter pattern is changed here by thread, but it won't reflect to other threads formatter.set(new SimpleDateFormat()); System.out.println("Thread Name= "+Thread.currentThread().getName()+" formatter = "+formatter.get().toPattern()); } }
這段代碼的輸出爲:ide
Thread Name= 0 default Formatter = yyyyMMdd HHmm Thread Name= 1 default Formatter = yyyyMMdd HHmm Thread Name= 0 formatter = yy-M-d ah:mm Thread Name= 2 default Formatter = yyyyMMdd HHmm Thread Name= 1 formatter = yy-M-d ah:mm Thread Name= 3 default Formatter = yyyyMMdd HHmm Thread Name= 4 default Formatter = yyyyMMdd HHmm Thread Name= 5 default Formatter = yyyyMMdd HHmm Thread Name= 2 formatter = yy-M-d ah:mm Thread Name= 6 default Formatter = yyyyMMdd HHmm Thread Name= 3 formatter = yy-M-d ah:mm Thread Name= 7 default Formatter = yyyyMMdd HHmm Thread Name= 8 default Formatter = yyyyMMdd HHmm Thread Name= 5 formatter = yy-M-d ah:mm Thread Name= 4 formatter = yy-M-d ah:mm Thread Name= 8 formatter = yy-M-d ah:mm Thread Name= 6 formatter = yy-M-d ah:mm Thread Name= 9 default Formatter = yyyyMMdd HHmm Thread Name= 7 formatter = yy-M-d ah:mm Thread Name= 9 formatter = yy-M-d ah:mm
從輸出能夠看到,Thread-0已經更改了formatter的值,可是Thread-2仍舊輸出了初始的formatter值,也就是說,線程擁有了本身的formatter變量。函數
ThreadLocal類在Java 8中擴展了一個新的方法withInitial(),它將函數式接口做爲參數,因此咱們能夠使用lambda表達式來輕鬆建立ThreadLocal實例。 例如,上面的格式化程序ThreadLocal變量能夠在一行中定義以下:spa
private static final ThreadLocal<SimpleDateFormat> formatter = ThreadLocal.<SimpleDateFormat>withInitial (() -> {return new SimpleDateFormat("yyyyMMdd HHmm");});
(完)線程