1,作用
ThreadLocal为每个线程提供了一个独立的副本。这样,线程之间的数据就相互隔离。
2,使用场景
由于和线程绑定,故在一些使用责任链模式的场景下,可以将上下文对象,放入ThreadLocal中。
3,代码示例
a)上下文对象
public class Context {
private String name;
private String id;
public void setName(String name) {
this.name = name;
}
public String getName(){
return this.name;
}
public void setId(String id) {
this.id = id;
}
public String getId() {
return id;
}
}
b)核心的线程上下文
/**
* 核心的线程上下文
*/
public class ActionContext {
private static final ThreadLocal<Context> threadLocal = ThreadLocal.withInitial(Context::new);
/**
* 利用Holder模式,完成单例模式
*/
private static class ContextHolder{
private final static ActionContext actionContext = new ActionContext();
}
public static ActionContext getInstance(){
return ContextHolder.actionContext;
}
public Context getContext(){
return threadLocal.get();
}
}
c)任务执行类
public class ExcutionTask implements Runnable {
private QueryFromDBAction queryAction = new QueryFromDBAction();
private QueryFromHttpAction httpAction = new QueryFromHttpAction();
@Override
public void run() {
//final Context context = new Context();
queryAction.execute();
System.out.println("query successful");
httpAction.execute();
final Context context = ActionContext.getInstance().getContext();
System.out.println("The name is "+context.getName()+"; "+context.getId());
}
}
d)其他两个Action补充
/**
* QueryFromDBAction
*/
public class QueryFromDBAction {
private final Random random = new Random(System.currentTimeMillis());
public void execute(){
try {
Thread.sleep(random.nextInt(1000));
String name = "Wayne:"+Thread.currentThread().getName();
ActionContext.getInstance().getContext().setName(name);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* QueryFromHttpAction
*/
public class QueryFromHttpAction {
private final Random random = new Random(System.currentTimeMillis());
public void execute(){
try {
Thread.sleep(random.nextInt(1000));
String id = "IDCard:"+Thread.currentThread().getId();
ActionContext.getInstance().getContext().setId(id);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
e)测试类
public class ContextPatternTest {
public static void main(String[] args) {
IntStream.range(1,5)
.forEach(i->{
new Thread(new ExcutionTask()).start();
});
}
}
4,测试结果