4.3 这一章节我们来讨论一下关于ThreadLocal的使用的时候需要注意的地方
ThreadLocal主要的使用是get、set、initialValue这几个方法,具体的使用我们这里不做介绍,下面只是举一些它使用的时候需要注意的地方。
1.在get方法的时候出现null
package com.ray.deepintothread.ch04.topic_3;
public class ThreadLocalGetNull {
private int count = 0;
public ThreadLocal<Integer> intThreadLocal = new ThreadLocal<Integer>();
public int getCount() {
return intThreadLocal.get();
}
public void addCount() {
intThreadLocal.set(count++);
}
public static void main(String[] args) {
System.out.println(new ThreadLocalGetNull().getCount());
}
}
输出:
Exception in thread “main” java.lang.NullPointerException
at com.ray.deepintothread.ch04.topic_3.ThreadLocalGetNull.getCount(ThreadLocalGetNull.java:10)
at com.ray.deepintothread.ch04.topic_3.ThreadLocalGetNull.main(ThreadLocalGetNull.java:18)
这里直接抛空指针异常,为什么?因为ThreadLocal的实现是通过Map来实现的,我将会在后一章节介绍ThreadLocal的实现原理
对于上面的问题,我们的解决方案是:初始化的时候使用initialValue方法。
package com.ray.deepintothread.ch04.topic_3;
public class SolutionOfThreadLocalGetNull {
private int count = 0;
public ThreadLocal<Integer> intThreadLocal = new ThreadLocal<Integer>() {
// 解决办法就是初始化数值
@Override
protected Integer initialValue() {
return count;
}
};
public int getCount() {
return intThreadLocal.get();
}
public void addCount() {
intThreadLocal.set(count++);
}
public static void main(String[] args) {
System.out.println(new SolutionOfThreadLocalGetNull().getCount());
}
}
输出:
0
在定义ThreadLocal之初就通过initialValue方法初始化返回的值。
2.ThreadLocal大部分的时间是使用在多线程的情况下,需要注意的是,每一个线程都只是使用ThreadLocal标注变量的副本进行计算
代码清单:(这里我沿用上一章节的例子)
package com.ray.deepintothread.ch04.topic_3;
public class ThreadLocalTest extends Thread {
private int count = 0;
public ThreadLocal<Integer> intThreadLocal = new ThreadLocal<Integer>() {
protected Integer initialValue() {
return count;
};
};
public int getCount() {
return intThreadLocal.get();
}
public void addCount() {
intThreadLocal.set(count++);
}
@Override
public void run() {
try {
for (int i = 0; i < 3; i++) {
addCount();
System.out.println("Thread[" + getName() + "] count[" + getCount() + "]");
sleep(50);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws InterruptedException {
new ThreadLocalTest().start();
Thread.sleep(100);
new ThreadLocalTest().start();
Thread.sleep(100);
new ThreadLocalTest().start();
}
}
输出:
Thread[Thread-0] count[0]
Thread[Thread-0] count[1]
Thread[Thread-1] count[0]
Thread[Thread-0] count[2]
Thread[Thread-1] count[1]
Thread[Thread-1] count[2]
Thread[Thread-2] count[0]
Thread[Thread-2] count[1]
Thread[Thread-2] count[2]
从输出我们可以看到,每一个线程操作的count的数值都是独立的,不被其他线程影响。
总结:这一章节我们讨论了ThreadLocal使用的两个注意的地方。
这一章节就到这里,谢谢