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

 

(完)线程

相关文章
相关标签/搜索