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

白话ThreadLocal类

阅读更多

ThreadLocal类在Spring等框架中扮演了一个很重要的角色,本文就从源码的角度揭开它羞涩的面纱。

废话不少,先看看可以怎么使用:

Person类:

public class Person {
	private String name;
	private int age;

	public Person(String name, int age)
	{
		this.name = name;
		this.age = age;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}

 TLPerson类:我理解为Person的线程变量包装类

public class TLPerson {
         //一般采用私有静态的方式定义
	private static ThreadLocal<Person> persontl = new ThreadLocal<Person>()
	{
		protected Person initialValue() {

	        return new Person("zubin" + Thread.currentThread().getId(), 31);

	    }
	};

	public Person getPerson()
	{
		Person p = persontl.get();
		if(p == null)
		{
			persontl.set(new Person("zubin" + Thread.currentThread().getName(),13));
   		        p = persontl.get();
		}
		return p;
	}

	public void setPerson(Person p)
	{
		persontl.set(p);
	}
}

 线程测试类:大家注意run方法中没有同步块

public class ThreadRunnable implements Runnable {
	TLPerson tlp;
	TLPerson tlp2;

	public ThreadRunnable(TLPerson tlp, TLPerson tlp2)
	{
		this.tlp = tlp;
		this.tlp2 = tlp2;
	}

	public void run() {
		System.out.println(tlp.getPerson().getName() + " : " +tlp.getPerson().getAge());
		tlp2.setPerson(new Person("abc" + Thread.currentThread().getId() ,33));
		System.out.println(tlp2.getPerson().getName() + " : " +tlp2.getPerson().getAge());
	}

	public static void main(String ... args)
	{
		TLPerson tlp = new TLPerson();
		TLPerson tlp2 = new TLPerson();

		ThreadRunnable tr1 = new ThreadRunnable(tlp, tlp2);
		ThreadRunnable tr2 = new ThreadRunnable(tlp, tlp2);

		new Thread(tr1).start();
		new Thread(tr2).start();
	}
}

 运行下测试线程,结果如下:

zubin7 : 31
abc7 : 33
zubin8 : 31
abc8 : 33

从结果可以看出,虽然两个线程都使用了相同的“TLPerson”,但是互相之间并无影响。


为什么呢,先来看ThreadLocal和Thread的关系


从上图可以看出,ThreadLocal和Thread是通过ThreadLocalMap这个内部类关联在一起的。

look:

public class Thread implements Runnable {

。。。

/*
     * InheritableThreadLocal values pertaining to this thread. This map is
     * maintained by the InheritableThreadLocal class.
     */
    ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

。。。

} 

step1:

当我们在创建Thread对象

ThreadRunnable tr1 = new ThreadRunnable(tlp, tlp2);
new Thread(tr1).start();

这时tr1的inheritableThreadLocals为空。

step2:

tr1开始执行run方法,执行

System.out.println(tlp.getPerson().getName() + " : " +tlp.getPerson().getAge());

我们看下tlp.getPerson()是怎么做的?

step3:

public Person getPerson()
    {
        Person p = persontl.get();
        if(p == null)
        {
            persontl.set(new Person("zubin" + Thread.currentThread().getName(),13));
            p = persontl.get();
        }

        return p;
    }

 从 persontl.get()方法进去了,我们看一下ThreadLocal的实现:

 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();
    }

    获取当前线程t的map,这个时候肯定是为null,所以会执行 setInitialValue()方法

private T setInitialValue() {
        T value = initialValue();
        Thread t = Thread.currentThread();
        ThreadLocalMap map = getMap(t);
        if (map != null)
            map.set(this, value);
        else
            createMap(t, value);
        return value;
    }

    首先通过 initialValue()方法获取初始值,这个方法我们在匿名内部类做了重写

 

private static ThreadLocal<Person> persontl = new ThreadLocal<Person>()
	{
		protected Person initialValue() {
	        return new Person("zubin" + Thread.currentThread().getId(), 31);
	    }
	};

   然后去获取map,ThreadLocalMap map = getMap(t);这个时候map还是为空,进入createMap()方法

 

void createMap(Thread t, T firstValue) {
        t.threadLocals = new ThreadLocalMap(this, firstValue);
    }

  在这个方法里才给Thread创建了map,并且把new Person("zubin" + Thread.currentThread().getId(), 31);对象存入map中。

  注意了,是new的一个对象哟,这是理解ThreadLocal的关键

 

		ThreadRunnable tr2 = new ThreadRunnable(tlp, tlp2);
		new Thread(tr2).start();

 tr2重复了step1、2、3.

 

O(∩_∩)O哈哈~,到次我们发现每个线程都有一个map,里面存放的以ThreadLocal对象为key,new的“共享”变量为value。也就是说每个线程的对象都是自己私人的,当然也就不会存在同步的问题了。

好处就是以空间换时间了,没有锁竞争了。

 

 

2
1
分享到:
评论

相关推荐

    JAVA ThreadLocal类深入

    【JAVA ThreadLocal类深入】 Java中的ThreadLocal类是一种线程绑定机制,用于在多线程环境中为每个线程提供独立的变量副本,避免了线程间的数据共享带来的并发访问问题。ThreadLocal并不是一个线程对象,而是线程...

    java中ThreadLocal类的使用

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

    简单分析Java线程编程中ThreadLocal类的使用共

    Java线程编程中的ThreadLocal类是一个非常重要的工具,它在多线程环境下提供了一种线程局部变量的机制。ThreadLocal并非是简单的变量,而是一种能够确保每个线程都拥有独立副本的变量容器。理解ThreadLocal的工作...

    ThreadLocal应用示例及理解

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

    Java 中ThreadLocal类详解

    Java中的ThreadLocal类是一个强大的工具,它允许程序员创建线程局部变量。这意味着每个线程都有其自己独立的、不可见的变量副本,从而避免了线程间的数据共享问题,简化了多线程环境下的编程复杂性。ThreadLocal并不...

    Java ThreadLocal类应用实战案例分析

    Java ThreadLocal类应用实战案例分析 Java ThreadLocal类是Java语言中的一种线程局部变量机制,允许每个线程都拥有自己的变量副本,从而避免了多线程之间的变量冲突。在本文中,我们将通过实战案例分析Java ...

    理解的ThreadLocal类的相关源码(用于博文引用源码下载)

    Java中ThreadLocal工具类(解决多线程程序中并发问题的一种新思路,主要为参数的拷贝问题),感兴趣的话可以查看博文,博文地址:http://blog.csdn.net/otengyue/article/details/38459327

    入研究java.lang.ThreadLocal类.docx

    ### 知识点详解:Java.lang.ThreadLocal 类 #### 一、概述 **ThreadLocal** 并非线程的一种特殊实现形式,而是一种为每个线程提供独立副本的机制,通常被称为“线程局部变量”。这种机制使得每个线程都可以独立...

    ThreadLocal

    ThreadLocal是Java编程语言中的一个类,用于在多线程环境中提供线程局部变量。它是一种特殊类型的变量,每个线程都有自己的副本,互不影响,从而实现线程间数据隔离。ThreadLocal通常被用来解决线程共享数据时可能...

    DBUTILs的ThreadLocal

    DbUTils中用ThreadLocal类

    ThreadLocal 内存泄露的实例分析1

    `ThreadLocal` 是 Java 中用于在单个线程内存储线程局部变量的类,每个线程都有自己的副本,不会互相干扰。`MyThreadLocal` 是 `ThreadLocal` 的子类,用于存储 `MyCounter` 对象。在 `LeakingServlet` 的 `doGet` ...

    事务的封装和Threadlocal实例

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

    ThreadLocal整理.docx

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

    ThreadLocal简单Demo

    2. **内部类ThreadLocalMap**: `ThreadLocalMap`是`ThreadLocal`类中的一个内部静态类,它是一个定制的哈希映射,专门用于存储线程局部变量。每个`Thread`对象都包含一个`ThreadLocalMap`实例,用于保存该线程的`...

    设计模式及ThreadLocal资料

    本资料主要聚焦于两种设计模式以及Java中的ThreadLocal特性。 首先,我们来探讨单例模式。单例模式是一种确保一个类只有一个实例,并提供全局访问点的设计模式。在Java中,通常通过私有构造函数、静态工厂方法或...

    java 简单的ThreadLocal示例

    Java中的ThreadLocal是一个非常重要的工具类,它在多线程编程中扮演着独特角色,尤其在处理线程间数据隔离和共享时。ThreadLocal不是线程本身,而是为每个线程提供一个独立的变量副本,使得每个线程都可以独立地改变...

Global site tag (gtag.js) - Google Analytics