以下内容转自http://ifeve.com/java-theadlocal/

Java中的ThreadLocal类可以让你创建的变量只被同一个线程进行读和写操作。因此,尽管有两个线程同时执行一段相同的代码,而且这段代码又有一个指向同一个ThreadLocal变量的引用,但是这两个线程依然不能看到彼此的ThreadLocal变量域。

1、创建一个ThreadLocal对象

如下所示,创建一个ThreadLocal变量:

private ThreadLocal myThreadLocal = new ThreadLocal();

你实例化了一个ThreadLocal对象。每个线程仅需要实例化一次即可。虽然不同的线程执行同一段代码时,访问同一个ThreadLocal变量,但是每个线程只能看到私有的ThreadLocal实例。所以不同的线程在给ThreadLocal对象设置不同的值时,他们也不能看到彼此的修改。

2、访问ThreadLocal对象

一旦创建了一个ThreadLocal对象,你就可以通过以下方式来存储此对象的值:

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

也可以直接读取一个ThreadLocal对象的值:

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

get()方法会返回一个Object对象,而set()方法则依赖一个Object对象参数。

3、ThreadLocal泛型

为了使get()方法返回值不用做强制类型转换,通常可以创建一个泛型化的ThreadLocal对象。以下就是一个泛型化的ThreadLocal示例:

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

现在你可以存储一个字符串到ThreadLocal实例里,此外,当你从此ThreadLocal实例中获取值的时候,就不必要做强制类型转换。

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

4、初始化ThreadLocal

由于ThreadLocal对象的set()方法设置的值只对当前线程可见,那有什么方法可以为ThreadLocal对象设置的值对所有线程都可见。

为此,我们可以通过ThreadLocal子类的实现,并覆写initialValue()方法,就可以为ThreadLocal对象指定一个初始化值。如下所示:

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

此时,在set()方法调用前,当调用get()方法的时候,所有线程都可以看到同一个初始化值。

5、Full ThreadLocal Example

以下是一个完整的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) throws InterruptedException {
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对象,所以两个线程无法看到彼此的值。因此,可以设置或者获取不同的值。

6、InheritableThreadLocal

InheritableThreadLocal类是ThreadLocal的子类。为了解决ThreadLocal实例内部每个线程都只能看到自己的私有值,所以InheritableThreadLocal允许一个线程创建的所有子线程访问其父线程的值。

测试工程:https://github.com/easonjim/5_java_example/tree/master/javathread/test3

14、Java并发性和多线程-Java ThreadLocal的更多相关文章

  1. 13、Java并发性和多线程-Java Volatile关键字

    以下内容转自http://tutorials.jenkov.com/java-concurrency/volatile.html(使用谷歌翻译): Java volatile关键字用于将Java变量标 ...

  2. 11、Java并发性和多线程-Java内存模型

    以下内容转自http://ifeve.com/java-memory-model-6/: Java内存模型规范了Java虚拟机与计算机内存是如何协同工作的.Java虚拟机是一个完整的计算机的一个模型, ...

  3. 21、Java并发性和多线程-Java中的锁

    以下内容转自http://ifeve.com/locks/: 锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂.因为锁(以及其它更高级的 ...

  4. 12、Java并发性和多线程-Java同步块

    以下内容转自http://ifeve.com/synchronized-blocks/: Java 同步块(synchronized block)用来标记方法或者代码块是同步的.Java同步块用来避免 ...

  5. 22、Java并发性和多线程-Java中的读/写锁

    以下内容转自http://ifeve.com/read-write-locks/: 相比Java中的锁(Locks in Java)里Lock实现,读写锁更复杂一些.假设你的程序中涉及到对一些共享资源 ...

  6. java 并发性和多线程 -- 读感 (一 线程的基本概念部分)

    1.目录略览      线程的基本概念:介绍线程的优点,代价,并发编程的模型.如何创建运行java 线程.      线程间通讯的机制:竞态条件与临界区,线程安全和共享资源与不可变性.java内存模型 ...

  7. Java 并发和多线程(一) Java并发性和多线程介绍[转]

    作者:Jakob Jenkov 译者:Simon-SZ  校对:方腾飞 http://tutorials.jenkov.com/java-concurrency/index.html 在过去单CPU时 ...

  8. Java并发性和多线程

    Java并发性和多线程介绍   java并发性和多线程介绍: 单个程序内运行多个线程,多任务并发运行 多线程优点: 高效运行,多组件并行.读->操作->写: 程序设计的简单性,遇到多问题, ...

  9. Java并发性和多线程介绍

    java并发性和多线程介绍: 单个程序内运行多个线程,多任务并发运行 多线程优点: 高效运行,多组件并行.读->操作->写: 程序设计的简单性,遇到多问题,多开线程就好: 快速响应,异步式 ...

随机推荐

  1. PHP 操作数据库乱码 以及调试

    mysql> show create database pxscj;+----------+--------------------------------------------------- ...

  2. [转]mysql update操作

    转自:http://www.cnblogs.com/ggjucheng/archive/2012/11/06/2756392.html update语法 Single-table语法: UPDATE ...

  3. C#知识点-枚举器和迭代器

    一.几个基本概念的理解 问题一:为什么数组可以使用foreach输出各元素 答:数组是可枚举类型,它实现了一个枚举器(enumerator)对象:枚举器知道各元素的次序并跟踪它们的位置,然后返回请求的 ...

  4. Scala-基础-数组(1)

    import junit.framework.TestCase import scala.collection.mutable.ArrayBuffer; //数组(1) //知识点-定义数组,变长数组 ...

  5. Python学习日记之正则表达式re模块

    用在线网页测试正则表达式时,JavaScript不支持 零宽度正回顾后发断言 (?<=exp)测试时一直匹配失败 但re模块是支持 (?<=exp) 的 终于脱坑

  6. Android常见问题总结(二)

    1.布局文件LinearLayout线性布局添加内容报错. 解决方法: 线性布局LinearLayout中包裹的元素多余1个需要添加android:orientation属性. 2.android 的 ...

  7. Java屏幕截图及剪裁

    Java标准API中有个Robot类,该类可以实现屏幕截图,模拟鼠标键盘操作这些功能.这里只展示其屏幕截图. 截图的关键方法createScreenCapture(Rectangle rect) ,该 ...

  8. acm练习-day1

    描述现在,有一行括号序列,请你检查这行括号是否配对.输入第一行输入一个数N(0<N<=100),表示有N组测试数据.后面的N行输入多组输入数据,每组输入数据都是一个字符串S(S的长度小于1 ...

  9. PSP辅助软件开发计划

    PSP辅助软件开发计划 作者: 日期:2013年11月14号 1开发目的 鉴于软件开发过程中,程序员往往无法在规定时间内完成任务,而且无法给出拖延的时间从而造成项目进度计划不准确.开发此软件帮助程序员 ...

  10. Jmeter之关联——常用提取器

    Jmeter关联 所谓关联,从业务角度讲,即:某些操作步骤与其相邻步骤存在一定的依赖关系,导致某个步骤的输入数据来源于上一步的返回数据,这时就需要“关联”来建立步骤之间的联系. 简单来说,就是:将上一 ...