专栏名称: ImportNew
伯乐在线旗下账号,专注Java技术分享,包括Java基础技术、进阶技能、架构设计和Java技术领域动态等。
目录
相关文章推荐
51好读  ›  专栏  ›  ImportNew

使用 ThreadLocal 变量的时机和方法

ImportNew  · 公众号  · Java  · 2017-05-16 15:04

正文

(点击 上方蓝字 ,快速关注我们)


编译:ImportNew - Angus

如有好文章投稿,请点击 → 这里了解详情


并发编程中,一个重要的内容是数据共享。当你创建了实现Runnable接口的线程,然后开启使用相同Runnable实例的各种Thread对象,所有 的线程便共享定义在Runnable对象中的属性。也就是说,当你在一个线程中改变任意属性时,所有的线程都会因此受到影响,同时会看到第一个线程修改后的值。有时我们希望如此,比如:多个线程增大或减小同一个计数器变量;但是,有时我们希望确保每个线程,只能工作在它自己的线程实例的拷贝上,同时不会影 响其他线程的数据。


使用ThreadLocal的时机


举个例子,想象你在开发一个电子商务应用,你需要为每一个控制器处理的顾客请求,生成一个唯一的事务ID,同时将其传到管理器或DAO的业务方法中,以便记录日志。一种方案是将事务ID作为一个参数,传到所有的业务方法中。但这并不是一个好的方案,它会使代码变得冗余。


你可以使用ThreadLocal类型的变量解决这个问题。首先在控制器或者任意一个预处理器拦截器中生成一个事务ID,然后在ThreadLocal中 设置事务ID,最后,不论这个控制器调用什么方法,都能从threadlocal中获取事务ID。而且这个应用的控制器可以同时处理多个请求,同时在框架 层面,因为每一个请求都是在一个单独的线程中处理的,所以事务ID对于每一个线程都是唯一的,而且可以从所有线程的执行路径获取。


扩展阅读 :《 与JAX-RS ResteasyProviderFactory共享上下文数据(ThreadLocalStack实例)》(http://howtodoinjava.com/resteasy/share-context-data-with-jax-rs-resteasyproviderfactory/)


ThreadLocal类


Java并发API为使用ThreadLocal类的局部线程变量提供了一个简洁高效的机制,


public class ThreadLocal extends Object {...}


这个类提供了一个局部线程变量。这些变量不同于其所对应的常规变量,对于常规变量,每个线程只能访问(通过get或set方法)其自身所拥有的,独立初始化变量拷贝。在一个类中,ThreadLocal类型的实例是典型的私有、静态(private static)字段,因为我们可以将其作为线程的关联状态(比如:用户ID或者事务ID)


这个类有以下方法:


  1. get():返回当前线程拷贝的局部线程变量的值。

  2. initialValue():返回当前线程赋予局部线程变量的初始值。

  3. remove():移除当前线程赋予局部线程变量的值。

  4. set(T value):为当前线程拷贝的局部线程变量设置一个特定的值。


怎样使用ThreadLocal?


下面的例子使用两个局部线程变量,即threadId和startDate。它们都遵循推荐的定义方法,即“private static”类型的字段。threadId用来区分当前正在运行的线程,startDate用来获取线程开启的时间。上面的信息将打印到控制台,以此验 证每一个线程管理他自己的变量拷贝。


class DemoTask implements Runnable {

// Atomic integer containing the next thread ID to be assigned

private static final AtomicInteger nextId = new AtomicInteger(0);

// Thread local variable containing each thread's ID

private static final ThreadLocal threadId =







请到「今天看啥」查看全文