[Java] ThreadLocal相关内容

        当谈到线程时,必然要关注多个线程对同一个资源的访问。比如某个线程要读一个变量,为了保证它在读的时候不被其它线程执行写操作,所以要加一个只读锁,这样其它线程就无法再加只写锁或读写锁,但是如果其它线程这时也要读它,可以再加只读锁。多个线程可以同时读这个变量,但是每次只有一个线程可以来写这个变量。这就是线程通过加锁的机制来访问变量。这种情况也就是同一个变量被多个线程共享,所以必须通过加锁进行同步。

         看了ThreadLocal的源码,发现和它相关的还有ThreadLocalMap和Thread。对Thread都应该比较熟悉,就是一个线程。ThreadLocalMap从表面上看就是一个ThreadLocal的Map,它里面保存的是多个ThreadLocal->Value(即从ThreadLocal到Value的映射,ThreadLocal用作键,Value是对应的值)。它们之间的关系是,Thread里面定义了一个ThreadLocalMap的变量threadLocals,并且没有进行初始化。当你在一个线程里面第一次访问ThreadLocal时,这个线程的threadLocals变量被初始化为ThreadLocalMap的对象。然后ThreadLocal的对象和对应的值就被存储到变量threadLocals里面。同一个线程可以访问多个ThreadLocal对象,它们和对应的值都存储在同一个变量threadLocals里面。换言之,一个线程有一个ThreadLocalMap类型的变量threadLocals,它里面保存了多个ThreadLocal的对象到对应值的映射。这就是一个线程访问多个ThreadLocal。同样,一个ThreadLocal也可以被多个线程访问,这样每一个线程的ThreadLocalMap类型的变量threadLocals里面都存储了ThreadLocal到对应值的映射。把上面两种情况结合起来,就是多个线程访问多个ThreadLocal。

        我们定义了一个ThreadLocal变量,每一个线程在访问它时,都会把这个变量和它对应的值放到线程里面,所以每个线程在读写时都是操作线程内部自己的拷贝。多个线程同时访问ThreadLocal时也不会有问题,我们定义的ThreadLocal变量并没有在线程间共享,而是每个线程自己拷贝了一份。所以不存在加锁和同步问题,当线程完成时,这个本地拷贝会随线程一起释放掉。

下面是一个简单的示例:

public static void main(String[] args) {
		
		final ThreadLocal<Integer> tl = new ThreadLocal<Integer>();
		
		new Thread(new Runnable(){
			public void run() {
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": get = " + tl.get());
				tl.set(10);
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": set = " + 10);
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": get = " + tl.get());
			}}).start();
		
		new Thread(new Runnable(){
			public void run() {
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": get = " + tl.get());
				tl.set(20);
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": set = " + 20);
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": get = " + tl.get());
			}}).start();
		
		new Thread(new Runnable(){
			public void run() {
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": get = " + tl.get());
				tl.set(30);
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": set = " + 30);
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": get = " + tl.get());
			}}).start();
		
		final ThreadLocal<Integer> tl0 = new ThreadLocal<Integer>();
		final ThreadLocal<Integer> tl1 = new ThreadLocal<Integer>();
		final ThreadLocal<Integer> tl2 = new ThreadLocal<Integer>();
		
		new Thread(new Runnable(){
			public void run() {
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": tl0.get = " + tl0.get());
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": tl1.get = " + tl1.get());
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": tl2.get = " + tl2.get());
				tl0.set(10);
				tl1.set(20);
				tl2.set(30);
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": tl0.set = " + 10);
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": tl1.set = " + 20);
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": tl2.set = " + 30);
				
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": tl0.get = " + tl0.get());
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": tl1.get = " + tl1.get());
				System.out.println("Thread ID = " + Thread.currentThread().getId() + ": tl2.get = " + tl2.get());
				
			}}).start();
	}


运行结果如下:

Thread ID = 7: get = null
Thread ID = 7: set = 10
Thread ID = 7: get = 10
Thread ID = 9: get = null
Thread ID = 9: set = 30
Thread ID = 9: get = 30
Thread ID = 8: get = null
Thread ID = 8: set = 20
Thread ID = 8: get = 20
Thread ID = 10: tl0.get = null
Thread ID = 10: tl1.get = null
Thread ID = 10: tl2.get = null
Thread ID = 10: tl0.set = 10
Thread ID = 10: tl1.set = 20
Thread ID = 10: tl2.set = 30
Thread ID = 10: tl0.get = 10
Thread ID = 10: tl1.get = 20
Thread ID = 10: tl2.get = 30

如果文章有什么不对地方,欢迎指出!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值