Concurrence-13-Java ThreadLocal


Java ThreadLocal


##### java的线程局部变量

文章的地址:翻译文章的源地址

java的类ThreadLocal可以使你创建的变量只会被同一个线程读或者写。因此即使是两个线程执行同一份代码,代码 中有一个指向ThreadLocal变量的引用,那么这两个线程是不能够看见对方的ThreadLocal变量的。

创建一个ThreadLocal

创建ThreadLocal 变量的代码:

private ThreadLocal myThreadLocal = new ThreadLocal();

上例所示,我们创建了一个ThreadLocal对象,每一个线程只需创建一个ThreadLocal变量,即使两个不同的线程执行 相同的代码访问一个ThreadLocal,每一个线程只会看到它自己的ThreadLocal实例,即使两个线程为同一个ThreadLocal 对象设置不同的值,他们是互不可见的。

####访问ThreadLocal

一个创建好的ThreadLocal对象,你可以这么进行进行设置存储值:

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

这样读取设置的值:

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

get()方法会返回一个Object类型的对象,而set方法则需要一个Object对象作为参数。

####ThreadLocal泛型 如果不想在get方法做类型转化,我们可以使用泛型,如下例:

private ThreadLocal myThreadLocal = new ThreadLocal<String>();

现在myThreadLocal实例可以保存String类型的数据,另外在从ThreadLocal实例中获得值的时候也不需要做类型 转化了:

myThreadLocal.set("Hello ThreadLocal");
String threadLocalValue = myThreadLocal.get();

####初始线程局部变量值 因为设置在ThreadLocal对象的值只能够对设置这个值的线程是可见的,使用set方法设置一个初始值对所有的线程 都是可见的,是行不通的。

但是你可以对一个ThreadL对象设置一个初始值通过创建ThreadLocal对象的子类,重载initialValue方法,如下:

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

这样的话,所有的线程都能够看到这个初始化,在没有调用set方法之前,通过get获取到这个值。

可运行的java 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();
    }

}

这个例子创建了一个MyRunnable实例,传递给两个不同的线程,两个线程执行run方法的时候,会向ThreadLocal变量 中设置不同的值,如果访问set方法是同步的,也不是一个ThreadLocal对象,那么第二个线程会覆盖第一个线程设 置的值。
然而,它是一个ThreadLocal对象,两个线程不能够见到对方的值,因此,它们会获得各自设置的值。

####InheritableThreadLocal

InheritableThreadLocal 是 ThreadLocal的子类,不同是是ThreadLocal是每一个线程都有自己的副本,InheritableThreadLocal 保证的是不仅创建它的线程能访问到,它的子线程也能够访问到。



上一篇  Concurrence-14-Thread Signaling 下一篇   算法-第一章