Java ThreadLocal

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");});

 

(完)線程

相關文章
相關標籤/搜索