声明:本文是《 Java 7 Concurrency Cookbook 》的第一章, 作者: Javier Fernández González 译者:郑玉婷 校对:方腾飞

使用本地线程变量

并发应用的一个关键地方就是共享数据。这个对那些扩展Thread类或者实现Runnable接口的对象特别重要。

如果你创建一个类对象,实现Runnable接口,然后多个Thread对象使用同样的Runnable对象,全部的线程都共享同样的属性。这意味着,如果你在一个线程里改变一个属性,全部的线程都会受到这个改变的影响。

有时,你希望程序里的各个线程的属性不会被共享。 Java 并发 API提供了一个很清楚的机制叫本地线程变量。

在这个指南中, 我们将开发一个程序,这个程序用来描述在第一段话里的问题,和另一个程序使用本地线程变量机制解决这个问题。

准备

指南中的例子是使用Eclipse IDE 来实现的。如果你使用Eclipse 或者其他的IDE,例如NetBeans, 打开并创建一个新的java项目。

怎么做呢

按照这些步骤来实现下面的例子:

1.   首先,我们来实现一个程序含有上述的问题。

创建一个类名为 UnsafeTask 并实现 Runnable 接口。 声明一个 private java.util.Date 属性.

1 public class UnsafeTask implements Runnable{
2 private Date startDate;

2. 实现UnsafeTask 对象的run() 方法,此方法会初始 startDate 属性, 把值写入控制台,随机休眠一段时间,最后在写入startDate 属性。

01 @Override
02 public void run() {
03 startDate=new Date();
04 System.out.printf("Starting Thread: %s : %s\n",Thread. currentThread().getId(),startDate);
05 try {
06 TimeUnit.SECONDS.sleep( (int)Math.rint(Math.random()*10));
07 catch (InterruptedException e) {
08 e.printStackTrace();
09 }
10 System.out.printf("Thread Finished: %s : %s\n",Thread. currentThread().getId(),startDate);
11 }

3.   现在,来实现这个有问题例子的主类。创建一个 Main  类和 main() 方法. 此方法会创建一个 UnsafeTask 类的对象,并开始3个线程使用这个对象,每个线程间休眠2秒。

01 public class Core {
02 public static void main(String[] args) {
03 UnsafeTask task=new UnsafeTask();
04  for (int i=0; i<10; i++){
05 Thread thread=new Thread(task);
06 thread.start();
07 try { TimeUnit.SECONDS.sleep(2);
08 catch (InterruptedException e) {
09 e.printStackTrace();
10 }
11 }
12 }
13 }

4.   在以下的裁图,你可以发现这个程序的执行结果。每个线程有着不同的开始时间,但是全部都有相同的结束时间。

5.   如在之前提到的, 我们会使用本地线程变量机制来解决这个问题。

6.   创建一个类名为 SafeTask a一定实现 Runnable 接口。

1 public class SafeTask implements Runnable {

7.   声明 ThreadLocal<Date> 类对象。此对象有隐含实现了 initialValue()方法. 此方法会返回真实日期。

1 private static ThreadLocal<Date> startDate= new ThreadLocal<Date>() {
2 protected Date initialValue(){
3 return new Date();
4 }
5 };

8.   实现run()方法。它和 UnsafeClass的run() 方法功能一样,只是改变了属性的访问方式。

01 @Override
02 public void run() {
03   System.out.printf("Starting Thread: %s : %s\n",Thread.currentThread().getId(),startDate.get());
04 try {
05   TimeUnit.SECONDS.sleep((int)Math.rint(Math.random()*10));
06 catch (InterruptedException e) {
07 e.printStackTrace();
08 }
09 System.out.printf("Thread Finished: %s : %s\n",Thread.currentThread().getId(),startDate.get());
10 }

9.    这个例子的主类跟不安全例子一样,把名字改成 Runnable 类。

10. 运行例子并分析不同处。

它是怎么工作的

在下面的截图里,你可以看到线程安全模式下程序运行的结果。现在3个 Thread 对象都有他们自己的startDate 属性值。看下图:

本地线程变量为每个使用这些变量的线程储存属性值。可以用 get() 方法读取值和使用 set() 方法改变值。 如果第一次你访问本地线程变量的值,如果没有值给当前的线程对象,那么本地线程变量会调用 initialValue() 方法来设置值给线程并返回初始值。

更多

本地线程类还提供 remove() 方法,删除存储在线程本地变量里的值。

Java 并发 API 包括 InheritableThreadLocal 类提供线程创建线程的值的遗传性 。如果线程A有一个本地线程变量,然后它创建了另一个线程B,那么线程B将有与A相同的本地线程变量值。 你可以覆盖 childValue() 方法来初始子线程的本地线程变量的值。 它接收父线程的本地线程变量作为参数。

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: 线程管理(九)使用本地线程变量

文章转自 并发编程网-ifeve.com

线程管理(九)使用本地线程变量相关推荐

  1. java线程本地变量_Java并发编程示例(九):本地线程变量的使用

    这篇文章主要介绍了Java并发编程示例(九):本地线程变量的使用,有时,我们更希望能在线程内单独使用,而不和其他使用同一对象启动的线程共享,Java并发接口提供了一种很清晰的机制来满足此需求,该机制称 ...

  2. java 线程的创建和执行_线程管理(一)线程的创建和运行

    声明:本文是< Java 7 Concurrency Cookbook>的第一章, 作者: Javier Fernández González 译者:郑玉婷 校对:欧振聪 线程的创建和运行 ...

  3. 线程管理(一)线程的创建和运行

    声明:本文是< Java 7 Concurrency Cookbook >的第一章, 作者: Javier Fernández González 译者:郑玉婷 校对:欧振聪 线程的创建和运 ...

  4. java的线程管理器,QuickThread - Java线程池管理器

    QuickThread 特性 任务扩展:支持延迟任务以及异步回调任务; 回调通知:当任务启动时与任务运行完毕后,有分别的生命周期作为通知; 线程切换:可制定是否回调主线程; 使用安全:当线程出现异常. ...

  5. java 线程管理_Java提供的线程池来创建多线程,进一步优化线程管理。

    提供最快小儿的阶段是发育生长. 根据型德增长模哈罗,程池为(增长率应,为投转化资要使储蓄全部,率为储蓄,本-比为产量若资. 在凯主义论中的经济周恩斯期理,建多进关系理的原理乘数和加速原是(.不能现代领 ...

  6. Android线程管理(一)

    线程通信.ActivityThread及Thread类是理解Android线程管理的关键. 线程,作为CPU调度资源的基本单位,在Android等针对嵌入式设备的操作系统中,有着非常重要和基础的作用. ...

  7. 《C++ Concurrencyin Action》第2章--线程管理

    前言 本章主要内容: 1 启动新线程 2 等待线程与分离线程 3 线程唯一标识符 好的!看来你已经决定使用多线程了.先做点什么呢?启动线程.结束线程,还是如何监管线程?在C++标准库中只需要管理std ...

  8. Unix进程和线程管理及其异同

    Unix进程和线程管理及其异同 一,进程 1,什么是进程 在最初的单处理器系统中,系统中的多道程序按照一定规则切换而实现多任务处理,后来发现多个程序并发导致系统资源被共享,为了描述和管理程序对共享资源 ...

  9. Nachos线程管理

    Nachos线程管理 Nachos中的线程是在内核中以一个thread类的对象的方式实现的.线程控制块是以类的数据成员的方式实现. //thread类源代码--定义 class Thread { pr ...

最新文章

  1. Fins TCP协议
  2. 害怕抑郁症?该系统通过日常交流就能判断你是否有病
  3. MATLAB的var与std函数 与 均值,方差,标准差,均方差,均分误差
  4. ORACLE新建表空间
  5. Sublime删除所有包含特定值的行
  6. Redis 实现用户积分排行榜
  7. ezcad旋转轴标刻参数_激光打标机软件ezcad中菜单下的旋转轴标刻功能介绍及其操作设置...
  8. 多元线性回归矩阵求导
  9. jenkins下载安装及环境搭建
  10. 经纬度坐标转换为大地2000怎么转换_XOMAP-爬虫[4]-零代码实现将quot;地址quot;转换为“经纬度”坐标及“结构化地址”...
  11. 局域网查共享计算机的ip地址吗,如何查看电脑的内网IP地址?
  12. 采用现场总线协议的压力变送器特性介绍
  13. qq邮箱发件转发php,phpmailer 利用qq邮箱转发邮件的问题
  14. unity测量模型尺寸
  15. Unity3d-简单AR游戏
  16. 为什么很多IT公司不喜欢进过培训机构的人呢?
  17. 华为nova6se怎么升级鸿蒙,华为EMUI11支持哪些手机
  18. 人工智能交互系统界面设计(Tkinter界面设计)
  19. 申请加精—ERP实施方法论的比较(SAP、 Oracle、J.D.E、BANN、用友等实施方法论)...
  20. 面对中小型机房动力环境该如何实现监控?

热门文章

  1. Jenkins构建Spring+Nodejs项目
  2. 判断标签是否出界,重新设置样式
  3. 【MySql】linux下,设置mysql表名忽略大小写
  4. struts2+spring3+hibernate3+mysql简单登录实现
  5. IOS 上传ipa文件失败
  6. 一个计算机爱好者的不完整回忆(二十八)关于计算机书籍
  7. STM32F103实现点灯(固件库方式)
  8. 51芯片4*4列阵按键c语言程序,单片机城中社稷.doc
  9. php中解析数组,在PHP中解析多维数组
  10. rabbin负载均衡