Java并发编程(Java Concurrency)(14)- Java ThreadLocal 类

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

摘要:这是翻译自一个大概30个小节的关于Java并发编程的入门级教程,原作者Jakob Jenkov,译者Zhenning Lang,转载请注明出处,thanks and have a good time here~~~(希望自己不要留坑)

Java 中的 ThreadLocal 类让你可以创建只能被相同的线程读写的变量。因此,即便是两个线程在执行同一段代码,同时这段代码拥有 ThreadLocal 变量的引用,此时,这两个线程的 ThreadLocal 变量对于对方都是不可见的。

1. 创建 ThreadLocal 变量

下面的例子展示了如何创建一个 ThreadLocal 变量:

private ThreadLocal myThreadLocal = new ThreadLocal();

上例创建并初始化了一个 ThreadLocal 对象。虽然多个线程都可以处理 ThreadLocal 变量(拥有 ThreadLocal 变量的引用),但每个线程只能获取其自己的 ThreadLocal 实例的值。

即便两个线程对同一个 ThreadLocal 对象设置了不同的值,这两个线程所设置的值对于对方也都是不可见的。

(通俗地讲,就是看起来好像每个线程都创建了该线程(Thread)的本地(Local)的变量一样,如果这个不大好理解,可以直接看第 5 部分的示例代码)

2. 读写 ThreadLocal 变量

一旦创建了 ThreadLocal 变量,你可以通过类似下面的代码来设置其取值:

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

通过如下代码来读取 ThreadLocal 变量的值:

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

ThreadLocal 变量的 get() 方法返回类型为 Object,而 set() 方法以 Object 对象作为输入函数。

3. ThreadLocal 范型

如果利用 ThreadLocal 范型则不必再对 get() 方法的返回值进行强制类型转换,例如:

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

此时,myThreadLocal 中只能存储 String 类型的变量。

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

4. 初始化 ThreadLocal 的值

由于 ThreadLocal 对象的值只对设置该值的对象是可见的,所以没有任何线程可以利用 set() 方法初始化一个对所有线程都可见的 ThreadLocal 的初始值。

取而代之的,可以通过继承 ThreadLocal 并覆盖 initialValue() 方法来指定其初始值,如下例所示:

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

如此一来,所有使用 myThreadLocal 的线程在调用 set() 方法之前都可以通过 get() 方法获取这个初始值(”This is the initial value”)。

5. 完整的 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() 方法被声明为 synchronized 的(?),并且没有使用 ThreadLocal 对象,后被执行的线程将会覆盖先执行线程所写的值。

然而,由于使用了 ThreadLocal 类,则两个线程对于 ThreadLocal 对象所写的值将不会相互影响,即例子中会打印出不同的值。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值