Java并发实践说:
ThreadLocal仅在线程本地值的生存期受任务限制的情况下才可以在池线程中使用;不应在池线程中使用ThreadLocal在任务之间传递值。
我对以上引用的理解是:ThreadLocal
在Runnable
的run()
末尾应清楚。我说的对吗?
下面的代码片段显示了当您忘记清除时的问题。
package com.example.schedulerdemo;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class EndlessShutdownHook {
public static void main(String[] args) {
ExecutorService executorService = Executors.newSingleThreadExecutor();
ThreadLocal<String> cache = new ThreadLocal<>();
executorService.execute(new AuthenticationTask("1234", cache));
executorService.execute(new AuthenticationTask("5678", cache)); // expect to print 5678, but print 1234
executorService.shutdown();
}
}
class AuthenticationTask implements Runnable {
private final String token;
private final ThreadLocal<String> threadLocal;
AuthenticationTask(String token, ThreadLocal<String> cache) {
this.token = token;
this.threadLocal = cache;
}
@Override
public void run() {
String username = threadLocal.get();
if (null != username) {
System.out.printf("username: %s\n", username);
} else {
if (null != token) {
username = getUsernameByToken(token);
threadLocal.set(username);
System.out.printf("username: %s\n", username);
} else {
System.out.println("token is null");
}
}
// execute other logic after authenticating
// forget to clear ThreadLocal
}
private String getUsernameByToken(String token) {
return token;
}
}