java threadlocal用法_Java ThreadLocal的用法解析

简介

java中经常使用ThreadLocal作为处理高并发访问的可选手段,ThreadLocal并不是一个线程,而是”以线程为作用域“的一种面向对象的数据结构。其用法的也有着让人难以理解的怪异性。

代码实战

定义一个线程类,其中定义了一个ThreadLocal 的对象

class AutoIntegerThread extends Thread

{

//静态局部变量(注意java中的静态变量的生命周期,共享性,唯一性)

private static ThreadLocal autoInteger = new ThreadLocal();

//自增次数

private int runTimes;

public AutoIntegerThread(int runTimes)

{

this.runTimes = runTimes;

}

@Override

public void run()

{

//为了说明ThreadLocal以线程为作用域,这里不适用同步代码块

if(autoInteger.get()==null)

{

autoInteger.set(new Integer(0));

}

for (int i = 0; i 

{

autoInteger.set(autoInteger.get()+1);

//这里使用以下,保证完整打印一下

synchronized (autoInteger)

{

System.out.println(getName()+"==>"+autoInteger.get().intValue());

}

}

}

public  Integer getFinalInteger()

{

return autoInteger.get();

}

}

测试代码

public class TestThreadLocal {

public static void main(String[] args)

{

AutoIntegerThread ait_1 = new AutoIntegerThread(5);

AutoIntegerThread ait_2 = new AutoIntegerThread(3);

AutoIntegerThread ait_3 = new AutoIntegerThread(3);

ait_1.setName("ait_1");

ait_2.setName("ait_3");

ait_3.setName("ait_2");

ait_1.start();

ait_2.start();

ait_3.start();

}

}

打印结果

ait_1==>1

ait_2==>1

ait_2==>2

ait_2==>3

ait_1==>2

ait_3==>1

ait_1==>3

ait_3==>2

ait_1==>4

ait_3==>3

ait_1==>5

有上面的代码和代码注释可知,符合java中的静态变量的描述,【静态变量的生命周期和应用程序的生命周期完全相同。静态变量具有共享性,唯一性,也就是说是单例】

是的,静态变量可以说是一个完整的单例,但由打印结果可知,似乎情况却违反了这种逻辑。

首先仔细想想,单例的好处是降低了内存的使用,从而提高程序的执行效率(这里不可过分理解,其实,当静态变量太多时反而也会影响内存的回收,因为他的生命周期决定了他和程序时“同寿的”,静态变量尽量少用的好,万事讲究一个“度”),另外单例的唯一性说明了他非常适合做“同步锁”。

其次,从结果来看,貌似谁也没影响谁。有人质疑是不是 private 的问题,建议java基础不熟练的话就不要问这样的问题了,因为private只决定访问权限,而不决定变量的创建。因此也就说明了,以线程为作用域。

if(autoInteger.get()==null)

{

autoInteger.set(new Integer(0));

}

从这段代码来看,如果是List集合来说,只会运行一次,但程序似乎并没有这么做,而是分别在每个线程个执行了一次。

看看源代码

java.lang.ThreadLocal

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) {

@SuppressWarnings("unchecked")

T result = (T)e.value;

return result;

}

}

return setInitialValue();

}

很显然,这个域作为map的key而存在,也就是说以“线程域”来创建和读取数据

而这个map的是属于Thread,看下面的源码

ThreadLocalMap getMap(Thread t) {

return t.threadLocals;

}

然而,进一步证明了threadlocal使用线程域

java.lang.Thread

ThreadLocal.ThreadLocalMap threadLocals = null;

static class ThreadLocalMap {....}

反正是个map,版面估计不足,不粘了,大家可以去看看。

总结:ThreadLocal通过“线程域”可以实现作用域的区分,并使得程序更加高效

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值