对ThreadLocal的理解与使用举例

 

ThreadLocal(线程本地变量)存储特定线程的数据,为每个线程提供副本数据的数据。有一个比较好的使用例子是线程监听器的传递。当一个线程函数调用栈比较深,以及代码入口多样性。采用ThreadLocal使监听器作为线程内的全局对象,只须调用get就可获得监听器对象。若不采用此方法,则其中一种解决方式需要监听器随着函数栈传递(这种程序设计看起来太累赘糟糕了)。另外一种需要为每个线程提供一个静态对象,但是当多个线程并发是,就需要提供多个静态对象。在可扩充性上几乎没有。因此使用ThreadLocal对象可以很好得解决以上两个问题。实现同一个对象,在多个线程内有多个不同副本,有时还可以解决线程安全问题,比如数据库的获取连接和关闭。

首先,在每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,这个threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。

初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals(相当于一个Map对象)。所以可以说通过ThreadLocal创建的副本是存储在每个线程自己的threadLocals中的。每个线程可以有多个ThreadLocal对象。实例化ThreadLocal对象时若已经重写了initialValue()方法,则无需set()就可以直接get()。如下图

 

package Test;

public class ThreadLocalDemo {

	public static void main(String[] args) {
		ThreadLocalTest threadLocalTest = new ThreadLocalTest();
		Thread thread1 = new Thread("thread1") {
			public void run() {
				threadLocalTest.set();
				System.out.println(threadLocalTest.getId());
				System.out.println(threadLocalTest.getName());
			}
		};

		Thread thread2 = new Thread("thread2") {
			public void run() {
				threadLocalTest.set();
				System.out.println(threadLocalTest.getId());
				System.out.println(threadLocalTest.getName());
			}
		};
		thread1.start();
		thread2.start();
	}

}

class ThreadLocalTest{

	ThreadLocal<Long> id = new ThreadLocal<Long>();
	ThreadLocal<String> name = new ThreadLocal<String>();
	
	public void set() {
		id.set(Thread.currentThread().getId());
		name.set(Thread.currentThread().getName());;
	}
		
	public long getId() {
		return this.id.get();
	}
	
	public String getName() {
		return this.name.get();
	}
}

运行结果如下:

有上面的运行可见。同一个ThreadLocal对象在不同的线程里面有着不同的副本存储。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值