Java多線程17 使用ThreadLocal重新設計一個上下文設計模式

Java多線程目錄

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的定義和聲明

注意:在使用之前記得將上個線程中context舊值清除調,否則會重複調用(比如線程池操作)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章