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,測試結果