您当前的位置: 首页 > 

止步前行

暂无认证

  • 3浏览

    0关注

    247博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

线程中的ThreadLocal

止步前行 发布时间:2018-12-08 18:45:48 ,浏览量:3

一、引言

ThreadLocal 又名 线程局部变量 ,是 Java 中一种较为特殊的线程绑定机制,可以为每一个使用该变量的线程都提供一个变量值的副本,并且每一个线程都可以独立地改变自己的副本,而不会与其它线程的副本发生冲突。一般而言,通过 ThreadLocal 存取的数据总是与当前线程相关,也就是说,JVM 为每个运行的线程绑定了私有的本地实例存取空间,从而为多线程环境常出现的并发访问问题提供了一种 隔离机制 。

如果一段代码中所需要的数据必须与其他代码共享,那就看看这些共享数据的代码能否保证在同一个线程中执行?如果能保证,我们就可以把共享数据的可见范围限制在同一个线程之内,这样,无须同步也能保证线程之间不出现数据争用的问题。也就是说,如果某个变量要被某个线程 独享,那么我们就可以通过ThreadLocal来实现线程本地存储功能。

二、 对 ThreadLocal 的理解 1、 ThreadLocal 在 JDK 中的定义

ThreadLocal

This class provides thread-local variables. These variables differ from their normal counterparts(副本) 
in that each thread that accesses one (via its get or set method) has its own, independently initialized 
copy of the variable. ThreadLocal instances are typically private static fields in classes that wish to 
associate state with a thread ( e.g., a user ID or Transaction ID ). 
(如果我们希望通过将某个类的状态(例如用户ID、事务ID)与线程关联起来,那么通常在这个类中定义private static类型
的ThreadLocal 实例。)

Each thread holds an implicit reference to its copy of a thread-local variable as long as the thread 
is alive and the ThreadLocal instance is accessible; after a thread goes away, all of its copies of 
thread-local instances are subject to garbage collection (unless other references to these copies exist).
	public class Thread implements Runnable {
	
	    ...
	
	    /* ThreadLocal values pertaining to this thread. This map is maintained
	     * by the ThreadLocal class. */
	    ThreadLocal.ThreadLocalMap threadLocals = null;
	
	    ...
	}

我们可以从中摘出三条要点:

(1)、每个线程都有关于该 ThreadLocal变量 的私有值 

每个线程都有一个独立于其他线程的上下文来保存这个变量的值,并且对其他线程是不可见的。

(2)、独立于变量的初始值 

ThreadLocal 可以给定一个初始值,这样每个线程就会获得这个初始化值的一个拷贝,并且每个线程对这个值的修改对其他线程是不可见的。

(3)、将某个类的状态与线程相关联 

我们从JDK中对 ThreadLocal 的描述中可以看出,ThreadLocal 的一个重要作用是就是将类的状态与线程关联起来,这个时候通常的解决方案就是在这个类中定义一个 private static ThreadLocal 实例。

2、 应用场景

类 ThreadLocal 主要解决的就是为每个线程绑定自己的值,以方便其处理自己的状态。形象地讲,可以将 ThreadLocal 变量 比喻成全局存放数据的盒子,盒子中可以存储每个线程的私有数据。例如,以下类用于生成对每个线程唯一的局部标识符。线程 ID 是在第一次调用 uniqueNum.get() 时分配的,在后续调用中不会更改。

	import java.util.concurrent.atomic.AtomicInteger;
	
	public class UniqueThreadIdGenerator {
	
	    private static final AtomicInteger uniqueId = new AtomicInteger(0);
	
	    private static final ThreadLocal uniqueNum = new ThreadLocal() {
	        @Override
	        protected Integer initialValue() {
	            return uniqueId.getAndIncrement();
	        }
	    };
	
	    public static void main(String[] args) {
	        Thread[] threads = new Thread[5];
	        for (int i = 0; i             
关注
打赏
1657848381
查看更多评论
0.0405s