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

Thread类中的threadLocals 和ThreadLocal原理

阅读更多

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对象相当于线程私有财产(数据)的经纪人,为线程的私有财产(数据)提供存储和获取的代理功能,而私有财产存在Thread的ThreadLocalMap对象中

 

 

 

 

一个 ThreadLocal对象只对应一个值对象 ,多个ThreadLocal对象和相应的值存在线程中类型为ThreadLocalMap类型的threadLocals变量中

 

 

因为通常把多了属性封装在一个Map,而一个 ThreadLocal对象只对应这个map,但map存有多值,故会给人1个Threadlocal对应多个对象的错误印象

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

分享到:
评论

相关推荐

    ThreadLocal原理及在多层架构中的应用

    **线程局部变量(ThreadLocal)是Java编程中一个非常重要的概念,主要用于在多线程环境中为每个线程提供独立的变量...在多层架构中,ThreadLocal可以有效地提高代码的可读性和性能,但也需要谨慎使用,遵循最佳实践。

    ThreadLocal原理及在多层架构中的应用.pdf

    在Java中,ThreadLocal被广泛应用于Web中间件、服务端编程和微服务架构中,用以解决多线程环境下的数据隔离问题。 首先,ThreadLocal原理是基于每个线程创建一个私有的数据存储结构(ThreadLocalMap),使得线程...

    threadLocal

    ThreadLocal是Java编程语言中的一个线程局部变量类,它为每个线程提供了一个独立的变量副本,使得每个线程可以独立地改变自己的副本,而不会影响其他线程所对应的副本。这个特性在多线程环境下处理并发问题时非常...

    ThreadLocal原理分析图,visio软件打开

    ThreadLocal原理分析图,visio软件打开

    java中ThreadLocal类的使用

    Java中的`ThreadLocal`类是一个非常实用的工具,它提供了线程局部变量的功能。线程局部变量意味着每个线程都拥有自己独立的变量副本,互不干扰,这在多线程编程中尤其有用,可以避免数据共享带来的同步问题。下面...

    ThreadLocal应用示例及理解

    **线程局部变量(ThreadLocal)是Java编程中一个非常重要的工具类,它在多线程环境下提供了线程安全的数据存储。ThreadLocal并不是一个变量,而是一个类,它为每个线程都创建了一个独立的变量副本,使得每个线程都...

    深入理解 Java 之 ThreadLocal 工作原理1

    ThreadLocal是Java中用于线程局部变量的一个工具类,它的工作原理主要体现在如何在不同的线程之间隔离变量的副本,确保每个线程拥有自己的独立数据。这个设计模式在多线程编程中尤其有用,因为它避免了传统的同步...

    java中ThreadLocal详解

    在Java多线程编程中,`ThreadLocal`是一个非常重要的工具类,它提供了一种在每个线程内部存储线程私有实例的方法。通常情况下,当多个线程共享某个变量时,可能会引发线程安全问题。而`ThreadLocal`则提供了另一种...

    ThreadLocal整理.docx

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

    ThreadLocal

    在使用ThreadLocal时,理解其工作原理和限制是非常重要的。合理的使用能够帮助我们编写出更高效、更易于维护的多线程程序,但也要避免滥用,因为它可能会引入难以察觉的并发问题和内存管理问题。

    Java中ThreadLocal的设计与使用

    Java中的ThreadLocal是一个非常重要的工具类,它在多线程编程中扮演着独特角色,...总之,ThreadLocal是Java多线程编程中的一个强大工具,但使用时需谨慎,理解其工作原理和潜在风险,才能更好地利用它来解决实际问题。

    事务的封装和Threadlocal实例

    在这个例子中,`ConnectionHolder`类提供了一组静态方法来设置、获取和移除线程局部的`Connection`对象。当多个线程并发执行时,每个线程都可以安全地使用自己的`Connection`实例,而不会相互干扰。 总的来说,结合...

    JDK的ThreadLocal理解(一)使用和测试

    ThreadLocal是Java中的一个非常重要的线程安全工具类,它在多线程编程中扮演着独特的角色。通过创建ThreadLocal实例,我们可以为每个线程提供一个独立的变量副本,这些副本在各个线程之间互不影响,从而实现线程局部...

    ThreadLocal源码分析和使用

    ThreadLocal 的原理是通过一个 Map 来存储每一个线程的变量副本,Map 中元素的键为线程对象,而值对应线程的变量副本。这样,当线程访问 ThreadLocal 变量时,实际上是访问的自己的副本,而不会影响其他线程的副本。...

    ThreadLocal中内存泄漏和数据丢失问题的问题浅析及解决方案.docx

    当前线程保存了 ThreadLocalMap 作为自己的 local 属性,而 Map 中的 key 又弱引用了 ThreadLocal,从而达到了 ThreadLocal 不存数据,而数据存在 Thread 中,而根据 ThreadLocal 获取 Thread 中的值。 ...

    ThreadLocal 内存泄露的实例分析1

    at 中专门为每一个 web 应用...理解 `ThreadLocal` 的工作原理以及它如何与类加载器交互,是避免此类问题的关键。在实际开发中,应当养成良好的编程习惯,如使用后及时清理 `ThreadLocal` 变量,以防止内存资源的浪费。

    ThreadLocal的原理,源码深度分析及使用.docx

    ThreadLocal 的实现原理可以分为两个部分:第一部分是 ThreadLocal 对象的创建和管理;第二部分是 ThreadLocal 对象的访问和更新。 ThreadLocal 对象的创建和管理是通过 ThreadLocalMap 来实现的。 ...

    ThreadLocal的简单理解.doc

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

Global site tag (gtag.js) - Google Analytics