美文网首页Java 杂谈Android开发经验谈Android知识
Java多线程17 使用ThreadLocal重新设计一个上下文

Java多线程17 使用ThreadLocal重新设计一个上下文

作者: 香沙小熊 | 来源:发表于2019-01-28 16:33 被阅读17次

    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旧值清除调,否则会重复调用(比如线程池操作)

    相关文章

      网友评论

        本文标题:Java多线程17 使用ThreadLocal重新设计一个上下文

        本文链接:https://www.haomeiwen.com/subject/qnyajqtx.html