`
zhouchaofei2010
  • 浏览: 1106872 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Thread类中的threadLocals

 
阅读更多

ThreadLocal在1.6版本中不是用一个全局的Map来存各个线程的变量副本,而是在Thread类中有一个ThreadLocalMap的变量,然后用Thread.currentThread().threadLocals.get(this)来引用的各线程变量副本,这样避免了去同步全局的Map

 

ThreadLocal使用的简单例子:

 

 

package com.test;

public class TestNum {
	// ①通过匿名内部类覆盖ThreadLocal的initialValue()方法,指定初始值
	private static ThreadLocal<Integer> seqNum = new ThreadLocal<Integer>() {
		public Integer initialValue() {
			return 0;
		}
	};

	// ②获取下一个序列值
	public int getNextNum() {
		seqNum.set(seqNum.get() + 1);
		return seqNum.get();
	}

	public static void main(String[] args) {
		TestNum sn = new TestNum();
		// ③ 3个线程共享sn,各自产生序列号
		TestClient t1 = new TestClient(sn);
		TestClient t2 = new TestClient(sn);
		TestClient t3 = new TestClient(sn);
		t1.start();
		t2.start();
		t3.start();
	}

	private static class TestClient extends Thread {
		private TestNum sn;

		public TestClient(TestNum sn) {
			this.sn = sn;
		}

		public void run() {
			for (int i = 0; i < 3; i++) {
				// ④每个线程打出3个序列值
				System.out.println("thread[" + Thread.currentThread().getName() + "] --> sn["
						 + sn.getNextNum() + "]");
			}
		}
	}
}

 

 通常我们通过匿名内部类的方式定义ThreadLocal的子类,提供初始的变量值,如例子中①处所示。TestClient线程产生一组序列号,在③处,我们生成3个TestClient,它们共享同一个TestNum实例。运行以上代码,在控制台上输出以下的结果:

 

thread[Thread-0] --> sn[1]
thread[Thread-1] --> sn[1]
thread[Thread-2] --> sn[1]
thread[Thread-1] --> sn[2]
thread[Thread-0] --> sn[2]
thread[Thread-1] --> sn[3]
thread[Thread-2] --> sn[2]
thread[Thread-0] --> sn[3]
thread[Thread-2] --> sn[3]

 

考察输出的结果信息,我们发现每个线程所产生的序号虽然都共享同一个TestNum实例,但它们并没有发生相互干扰的情况,而是各自产生独立的序列号,这是因为我们通过ThreadLocal为每一个线程提供了单独的副本。

 

 

上面例子中,是在自己的类中定义ThreadLocal,那么,那么,可否直接使用Thread.currentThread().threadLocals?

 

不可以的,因为threadLocals变量在Thread中时package的访问权限,只能在同一个包下访问。

 

但是可以通过反射来得到threadLocals中的内容,参考:

 

http://stackoverflow.com/questions/2001353/java-list-thread-locals

 

 

threadLocals 是干什么用的?

 

是线程存放多个ThreadLocal实例的。

 

 

 

ThreadLocal首先通过当前线程t得到threadLocals,然后把自身this作为key,从threadLocals中得到存储在线程本地的相关的数据

 

ThreadLocal中get 和set方法如下:

 

 

 public void set(T value) {

        Thread t = Thread.currentThread();

        ThreadLocalMap map = getMap(t);

        if (map != null)

            map.set(this, value);

        else

            createMap(t, value);

    }

 

 

 

  public T get() {

        Thread t = Thread.currentThread();

        ThreadLocalMap map = getMap(t);

        if (map != null) {

            ThreadLocalMap.Entry e = map.getEntry(this);

            if (e != null)

                return (T)e.value;

        }

        return setInitialValue();

    }

    

    

    其中 getMap方法简单如下:

    

  ThreadLocalMap getMap(Thread t) {

        return t.threadLocals;

    }

 

 

 

 

总结ThreadLocal原理:ThreadLocal对象相当于线程私有财产(数据)的经纪人,为线程的私有财产(数据)提供存储和获取的功能

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    ThreadLocal的简单理解.doc

    最后,Thread 类是线程类,在这个类中存在一个 threadLocals 变量,具体的类型是 ThreadLocal.ThreadLocalMap。 五、ThreadLocal 如何实现 set 方法 set 方法的实现非常重要,它的实现过程如下: 1. 获取当前线程...

    ThreadLocal整理.docx

    这个功能是通过 Thread 类中的 threadLocals 属性来实现的,这个属性实际上是一个 Entry 数组,其中的每个 Entry 都是一个弱引用,易于在 GC 时被回收。 ThreadLocal 的工作机制是通过计算Hash值来确定在数组中的...

    java的ThreadLocal[整理].pdf

    Thread类是Java线程的基类,每个线程都有一个ThreadLocalMap实例,这是通过Thread类中的threadLocals字段实现的。当ThreadLocal的get()或set()方法被调用时,会检查当前线程的ThreadLocalMap,如果不存在,就会创建...

    多线程-572e342b467d4057bc1bb089fa0a8483.pdf

    ThreadLocal中包含一个ThreadLocalMap静态内部类,每个线程拥有一个ThreadLocalMap实例变量threadLocals,当调用set()、get()、remove()方法时,ThreadLocal通过当前线程对象获取对应的threadLocals对象,然后进行...

    ThreadLocal 线程本地变量 及 源码分析.rar_开发_设计

    - 在`ThreadLocal`的`get()`方法中,首先通过`Thread.currentThread().threadLocals`获取到当前线程的`ThreadLocalMap`,然后根据`this`(即当前的ThreadLocal实例)作为键查找值。 - `set()`方法中,首先检查`...

    32.8、高并发线程1

    3. `getMap(Thread t)`方法返回`t.threadLocals`,这是一个`ThreadLocalMap`实例,存储在线程的实例字段中。 4. `createMap(Thread t, T firstValue)`方法创建新的`ThreadLocalMap`并将第一个键值对插入其中,键为`...

    ThreadLocal

    - `ThreadLocal`类在`java.lang`包下,它的实现主要依赖于`Thread`类的成员变量`threadLocals`,这是一个`ThreadLocalMap`实例,`ThreadLocalMap`是`WeakReference&lt;ThreadLocal&lt;?&gt;&gt;`和`Object`(代表值)的键值对...

    运行在tomcat容器中的ThreadLocal容易产生的问题

    ThreadLocal在Java编程中是一个非常有用的工具类,它允许在每个线程中独立地存储变量副本,从而实现线程安全的变量隔离。然而,在特定环境下,如Tomcat这样的Servlet容器中,不恰当使用ThreadLocal可能会导致一些...

    有关ThreadLocal的面试题你真的懂了吗

    7. ThreadLocal的ThreadLocalMap:Thread类有属性变量threadLocals(类型是ThreadLocal.ThreadLocalMap),也就是说每个线程有一个自己的ThreadLocalMap。这样,每个线程往这个ThreadLocal中读写隔离的,并且是互相...

    ThreadLocal、InheritableThreadLocal详解

    这个映射存储在线程的成员变量threadLocals中。由于ThreadLocalMap的设计,ThreadLocal变量在没有被显式清理的情况下,可能会导致内存泄漏,因为线程可能长时间运行,而ThreadLocal对象已经不再使用,但仍然保留在...

    redar:Java Swift Knife 项目.. - 线程、Quartz、Spring、Spring Integration、Apache Mina、Python

    多线程示例####1.1 ThreadLocals + ThreadPools 该模块通过确保在 Runnable 执行结束时删除 ThreadLocal 上下文来测试内存泄漏保护####1.2。 分叉和加入本模块用于测试 Fork And Join ####1.3。 通过 RMI 使用信号...

    深入浅出的学习Java ThreadLocal

    1. **ThreadLocalMap**:每个`Thread`对象都有一个`threadLocals`字段,引用着一个`ThreadLocalMap`实例,这个Map用于存储每个线程的`ThreadLocal`变量及其对应的值。 2. **Entry**:`ThreadLocalMap`的内部类`...

Global site tag (gtag.js) - Google Analytics