高并发编程之上下文设计模式(使用ThreadLocal实现)

一、上下文设计模式简介
上下文就是贯穿整个系统或者阶段生命周期的对象,其中存贮了一些系统的全局变量信息。在很多时候,单个线程的执行任务步骤非常多的时候,后面的某一步骤需要前面的输出值(责任链模式中特别多),那么需要将参数从头传递到尾,这样会特别的麻烦,并且在参数过多的情况下更加不合适,那么这个时候就需要一个上下文作为上下文进行绑定线程传递了的.java为我们提供了一个很好的容器,就是ThreadLocal的。

二、ThreadLocal介绍
ThreadLocal类顾名思义可以理解为线程本地变量。也就是说如果定义了一个ThreadLocal,每个线程往这个ThreadLocal中读写是线程隔离,互相之间不会影响的。它提供了一种将可变数据通过每个线程有自己的独立副本从而实现线程封闭的机制。

三、使用ThreadLocal实现上下文设计模式的结构
①.Context 类::文本类,用来存储数据。
②.ActionContext 类:用来创建ThreadLocal对象(单例模式实现)以及获取Context对象。
③.ExecutionTask 类:执行任务类。
④.QueryFromDBAction 类:模拟数据库存放数据的类。
⑤.QueryFromHttpAction 类:从其他地方获取数据的类
⑥⑦⑧⑨⑩

四、Java代码实现
①.Context .class

package chapter2.context;

/**
 * @author czd
 */
public class Context {
    private String name;

    public void setId(String id) {
        this.id = id;
    }

    private String id;

    public String getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

②.ActionContext .class

package chapter2.context;

/**
 * @author czd
 */
public class ActionContext {

    private static final ThreadLocal<Context> threadLocal = new ThreadLocal<Context>(){
        @Override
        protected Context initialValue() {
            return new Context();
        }
    };

    private static class ContextHolder{
        private final static ActionContext actionContext = new ActionContext();
    }

    public static ActionContext getInstance(){
        return ContextHolder.actionContext;
    }

    public Context getContext(){
        return threadLocal.get();
    }

}

③.ExecutionTask.class

package chapter2.context;

/**
 * @author czd
 */
public class ExecutionTask implements Runnable{
    private QueryFromDBAction queryFromDBAction = new QueryFromDBAction();

    private QueryFromHttpAction queryFromHttpAction = new QueryFromHttpAction();


    @Override
    public void run() {
        Context context = ActionContext.getInstance().getContext();
        queryFromDBAction.execute();
        System.out.println("The name query success!");
        queryFromHttpAction.execute();
        System.out.println("The idt query success!");
        System.out.println("The name is" + context.getName() +"and The IdCard is" + context.getId());
    }
}

④.QueryFromDBAction .class

package chapter2.context;

/**
 * @author czd
 * 模拟从数据库中拿取数据
 */
public class QueryFromDBAction {
    public void execute(){
        try {
             Thread.sleep(1000);
             String name = "author" + Thread.currentThread().getName();
             ActionContext.getInstance().getContext().setName(name);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

⑤.QueryFromHttpAction .class

package chapter2.context;

/**
 * @author czd
 * 模拟从其他地方拿取数据
 */
public class QueryFromHttpAction {
    public void execute(){
        Context context = ActionContext.getInstance().getContext();
        String name = context.getName();
        String id = getCardId(name);
        context.setId(id);
    }

    public String getCardId(String name){
        try {
            Thread.sleep(1000);

        }catch (Exception e){
            e.printStackTrace();
        }
        return "身份证号码:123456789>>>>>" + Thread.currentThread().getId();
    }
}

⑥.ContextTest.class 测试类,main函数

package chapter2.context;

/**
 * @author czd
 */
public class ContextTest {
    public static void main(String[] args) {
        for(int i = 0; i < 5; i++){
            new Thread(new ExecutionTask()).start();
        }
    }
}

输出结果
在这里插入图片描述

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ThreadLocal是一个线程局部变量,它的值只能被当前线程访问和修改,其他线程无法访问。使用ThreadLocal可以很方便地在多线程环境下保持上下文的一致性。 下面是一个使用ThreadLocal实现上下文的示例代码: ```java public class Context { private static final ThreadLocal<String> context = new ThreadLocal<>(); public static void setContext(String value) { context.set(value); } public static String getContext() { return context.get(); } public static void clearContext() { context.remove(); } } ``` 在这个上下文类中,我们使用了一个ThreadLocal变量来存储上下文信息。setContext方法用于设置当前线程的上下文信息,getContext方法用于获取当前线程的上下文信息,clearContext方法用于清除当前线程的上下文信息。 下面是一个使用上下文的示例代码: ```java public class Worker implements Runnable { public void run() { Context.setContext("Thread-" + Thread.currentThread().getId()); // 执行任务 String context = Context.getContext(); System.out.println("Task executed in context: " + context); Context.clearContext(); } } public class Main { public static void main(String[] args) { ExecutorService executorService = Executors.newFixedThreadPool(10); for (int i = 0; i < 10; i++) { executorService.execute(new Worker()); } executorService.shutdown(); } } ``` 在这个示例中,我们创建了一个Worker类来执行任务。在Worker的run方法中,首先使用Context.setContext方法设置当前线程的上下文信息,然后执行任务,并使用Context.getContext方法获取当前线程的上下文信息,最后使用Context.clearContext方法清除当前线程的上下文信息。在Main类中,我们创建了一个线程池并提交了10个Worker任务,这些任务会在不同的线程中执行。当每个任务执行时,它会在自己的上下文中执行,保持了上下文的一致性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值