从头认识多线程-4.3 ThreadLocal使用时需要注意的地方

时间:2021-10-11 06:52:27

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使用的两个注意的地方。

这一章节就到这里,谢谢


我的github:https://github.com/raylee2015/DeepIntoThread

目录:http://blog.csdn.net/raylee2007/article/details/51204573