关于ThreadLocal变量的一个坑

每个线程都有一个ThreadLocalMap对象,ThreadLocalMap是Thread的一个内部类,可以把ThreadLocalMap理解成一个Map,这个Map里存放这一个Thread的所有线程变量。

在我们创建一个线程变量 maxLife 之后,执行其set方法,其实是以maxLife这个对象为键,以0为值,然后将这组键值对放入当前线程的ThreadLocalMap对象中。

如果你不明白这意味着什么,接着往下看。

为了说明ThreadLocal有什么不同,我们直接上代码。

首先,我们在类中定义一个全局变量,后边的所有线程都共享这个变量。

ThreadLocal<Integer> maxLife = null;

然后创建一个线程A,并在这个线程中为maxLife赋一个新对象,并且为其设置值

maxLife = new ThreadLocal<Integer>()
maxLife.set(0);

这个时候让A线程别再往下跑了,同时我们创建一个B线程,然后在B线程里

maxLife = new ThreadLocal<Integer>();

执行完这一段,把B暂停了,然后再回到A线程,执行

Integer i = maxLife.get();

这个时候你如果打印i,那么你会看到一个null。

这是为什么呢?

因为maxLife的get方法,其实是以maxLife这个对象本身为键,然后去当前线程的ThreadLocalMap中获取其所对应的值,A线程中我们new了一个对象然后当成key,B线程中我们又new了一个,我们知道A和B先后new 的两个对象不是同一个对象,那么以不同的对象作为key去一个map里面取值会怎样呢?

也就是说 maxLife 这个变量,在A和B中是共享的,但是maxLife作为key在A和B各自的ThreadLocalMap中对应的值是不一样的,所以我们定义ThreadLocal变量,最好在一开始的时候就为其new一个值,而不是让它等于null。

完毕。

上一篇:@Override 注解compiler1.5和compiler1.6不同


下一篇:Android中处理崩溃异常和记录日志