Java多執行緒17 使用ThreadLocal重新設計一個上下文設計模式
public class Context { private String name; private String cardId; public String getCardId() { return cardId; } public void setCardId(String cardId) { this.cardId = cardId; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } }
public class ExecutionTask implements Runnable { private QueryFromDBAction queryAction = new QueryFromDBAction(); private QueryFromHttpAction httpAction = new QueryFromHttpAction(); @Override public void run() { final Context context = new Context(); queryAction.execute(context); System.out.println("The name query successful"); httpAction.execute(context); System.out.println("The cardId query successful"); System.out.println("The Name is " + context.getName() + " and CardId " + context.getCardId()); } }
public class QueryFromDBAction { public void execute(Context context) { try { Thread.sleep(1000L); String name = "Jack " + Thread.currentThread().getName(); context.setName(name); } catch (InterruptedException e) { e.printStackTrace(); } } }
public void execute(Context context) { String name = context.getName(); String cardId = getCardId(name); context.setCardId(cardId); } private String getCardId(String name) { try { Thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } return "444555" + Thread.currentThread().getId(); } }
public class ContextTest { public static void main(String[] args) { IntStream.range(1, 5) .forEach(i -> new Thread(new ExecutionTask()).start() ); } }
The name query successful The name query successful The name query successful The name query successful The cardId query successful The Name is Jack Thread-0 and CardId 44455511 The cardId query successful The Name is Jack Thread-1 and CardId 44455512 The cardId query successful The Name is Jack Thread-2 and CardId 44455513 The cardId query successful The Name is Jack Thread-3 and CardId 44455514
問題:需要在每個呼叫Context的方法中傳入進去
public void execute(Context context) { }
使用ThreadLocal重新設計一個上下文設計模式
public final class ActionContext { private static final ThreadLocal<Context> threadLocal = new ThreadLocal() { @Override protected Object initialValue() { return new Context(); } }; public static ActionContext getActionContext() { return ContextHolder.actionContext; } public Context getContext() { return threadLocal.get(); } private static class ContextHolder { private final static ActionContext actionContext = new ActionContext(); } }
public class Context { private String name; private String cardId; public String getCardId() { return cardId; } public void setCardId(String cardId) { this.cardId = cardId; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } }
public class ExecutionTask implements Runnable { private QueryFromDBAction queryAction = new QueryFromDBAction(); private QueryFromHttpAction httpAction = new QueryFromHttpAction(); @Override public void run() { queryAction.execute(); System.out.println("The name query successful"); httpAction.execute(); System.out.println("The cardId query successful"); final Context context = ActionContext.getActionContext().getContext(); System.out.println("The Name is " + context.getName() + " and CardId " + context.getCardId()); } }
public class QueryFromDBAction { public void execute() { try { Thread.sleep(1000L); String name = "Jack " + Thread.currentThread().getName(); ActionContext.getActionContext().getContext().setName(name); } catch (InterruptedException e) { e.printStackTrace(); } } }
public class QueryFromHttpAction { public void execute() { Context context = ActionContext.getActionContext().getContext(); String name = context.getName(); String cardId = getCardId(name); context.setCardId(cardId); } private String getCardId(String name) { try { Thread.sleep(1000L); } catch (InterruptedException e) { e.printStackTrace(); } return "444555" + Thread.currentThread().getId(); } }
public class ContextTest { public static void main(String[] args) { IntStream.range(1, 5) .forEach(i -> new Thread(new ExecutionTask()).start() ); } }
The name query successful The name query successful The name query successful The name query successful The cardId query successful The Name is Jack Thread-3 and CardId 44455514 The cardId query successful The cardId query successful The Name is Jack Thread-0 and CardId 44455511 The cardId query successful The Name is Jack Thread-2 and CardId 44455513 The Name is Jack Thread-1 and CardId 44455512
這樣寫 執行過程中不會看到context的定義和宣告