ThreadLocal

原文链接: http://tutorials.jenkov.com/java-concurrency/threadlocal.html

文章目录

  • ThreadLocal简介
  • ThreadLocal使用
    • 创建ThreadLocal
    • 访问ThreadLocal
    • 给ThreadLocal设置初始值
    • ThreadLocal的完整使用用例

ThreadLocal简介

  ThreadLocal线程封闭:每个Thread线程内部都有一个map,这个map是以线程本地对象作为key,以线程的变量副本作为Value。同时这个map是由TreadLoal来维护的,由ThreadLocal负责向map里设置线程的变量值以及获取值。因此,即使两个线程正在执行相同的代码,并且代码具有对ThreadLocal变量的引用,那么两个线程也不能看到彼此的ThreadLocal变量,于是就形成了线程间副本的隔离,做到了多个线程互不干扰。

ThreadLocal使用

创建ThreadLocal

private ThreadLocal myThreadLocal = new ThreadLocal();

  上面是一个简单的ThreadLocal创建过程,通过实例化一个新的ThreadLocal对象。每个线程只需要执行一次。即使不同的线程执行访问ThreadLocal的相同代码,每个线程也只能看到自己的ThreadLocal实例。即使两个不同的线程在同一个ThreadLocal对象上设置了不同的值,它们也不能看到彼此的值。

访问ThreadLocal

  给ThreadLocal赋值:

myThreadLocal.set("A thread local value");

  获取ThreadLocal中的值

String threadLocalValue = (String) myThreadLocal.get();

  当然我们也可以使用通用的方法

private ThreadLocal<String> myThreadLocal = new ThreadLocal<String>();
myThreadLocal.set("Hello ThreadLocal");
String threadLocalValue = myThreadLocal.get();

给ThreadLocal设置初始值

  由于ThreadLocal对象上设置的值只对设置值的线程可见,所以没有线程可以使用set()ThreadLocal上设置初值,而set()对所有线程可见。

  不过这并不意味着我们不可以对ThreadLocal设置初始值,实际上我们可以通过覆盖ThreadLocal中的initialValue()方法为其设置初始值。

private ThreadLocal myThreadLocal = new ThreadLocal<String>() {
    @Override protected String initialValue() {
        return "This is the initial value";
    }
};    

  通过上述方法,在调用set()之前调用get()时,所有线程将看到相同的初始值。

ThreadLocal的完整使用用例

  下面是ThreadLocal的完整使用用例:

public class ThreadLocalExample {


    public static class MyRunnable implements Runnable {

        private ThreadLocal<Integer> threadLocal =
               new ThreadLocal<Integer>();

        @Override
        public void run() {
            threadLocal.set( (int) (Math.random() * 100D) );
    
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
            }
    
            System.out.println(threadLocal.get());
        }
    }


    public static void main(String[] args) {
        MyRunnable sharedRunnableInstance = new MyRunnable();

        Thread thread1 = new Thread(sharedRunnableInstance);
        Thread thread2 = new Thread(sharedRunnableInstance);

        thread1.start();
        thread2.start();

        thread1.join(); //wait for thread 1 to terminate
        thread2.join(); //wait for thread 2 to terminate
    }

}

  这个例子创建了一个MyRunnable实例,它被传递给两个不同的线程。两个线程都执行run()方法,因此在ThreadLocal实例上设置不同的值。如果对set()调用的访问已经同步,并且它不是ThreadLocal对象,那么第二个线程将覆盖第一个线程设置的值。

  但是,由于它是ThreadLocal对象,所以两个线程不能看到彼此的值。因此,它们设置并得到不同的值。

你可能感兴趣的:(高并发,高并发)