TPS04-J. 使用线程池时确保ThreadLocal变量每次都初始化

时间:2023-03-09 01:49:50
TPS04-J. 使用线程池时确保ThreadLocal变量每次都初始化

线程池可以提供这种保障,一旦你的代码开始执行了,被分配来执行这个task的线程在执行完你的task之前不会做别的事情。

所以不用担心执行到一半被别的task改了 thread local 的变量。

由于线程重复使用所以你对thread local变量的修改都会保留下来

所以在使用前要把变量“重置”一下。 可以在每个task结尾做,也可以在开始做。

在结尾做的话需要放到finally里,确保执行

public final class Diary {
// ...
public static void removeDay() {
days.remove();
}
} public final class DiaryPool {
// ...
public void doSomething1() {
exec.execute(new Runnable() {
@Override
public void run() {
try {
Diary.setDay(Day.FRIDAY);
diary.threadSpecificTask();
} finally {
Diary.removeDay(); // 就是这里
}
}
});
}
// ...
}

另一个方法是在每次执行task之前做清理。

具体实现起来就是对executor进行扩展实现 beforeExecute 方法

class CustomThreadPoolExecutor extends ThreadPoolExecutor {
public CustomThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
} @Override
public void beforeExecute(Thread t, Runnable r) {
if (t == null || r == null) {
throw new NullPointerException();
}
Diary.setDay(Day.MONDAY);
super.beforeExecute(t, r);
}
}