线程上下文设计模式

x33g5p2x  于2022-04-23 转载在 其他  
字(3.3k)|赞(0)|评价(0)|浏览(179)

一 点睛

在上一篇中,我们是通过 context 从头到尾进行传递,如果参数比较少还可以容忍,如果方法参数比较多,在七八次的调用甚至十几次的调用后,都需要从头到尾地传递 context,很显然是一种比较繁琐的设计,可以采用线程的上下文设计来解决这样的问题。

二 实战

1 线程上下文信息

package concurrent.context.improve;

/**
* 线程运行上下文设计模式
* 上下文
*
* @author cakin
*/
public class Context {
    private String name;
    private String cardId;

    public String getName() {
        return name;
    }

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

    public String getCardId() {
        return cardId;
    }

    public void setCardId(String cardId) {
        this.cardId = cardId;
    }
}

2 从数据库中查询数据

package concurrent.context.improve;

/**
* 线程运行上下文设计模式
* 从数据库查询数据
*
* @author cakin
*/
public class QueryFromDbAction {
    public void execute() {
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String name = "Alex-" + Thread.currentThread().getName();
        ActionContext actionContext = ActionContext.getInstance();
        Context context = actionContext.getContext();
        context.setName(name);
    }
}

3 从接口中获取数据

package concurrent.context.improve;

/**
* 线程运行上下文设计模式
* 调用接口获取数据
*
* @author cakin
*/
public class QueryFromHttpAction {
    public void execute() {
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        ActionContext actionContext = ActionContext.getInstance();
        Context context = actionContext.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 "510823" + Thread.currentThread().getId();
    }
}

4 单例包装线程上下文

package concurrent.context.improve;

/**
* 线程运行上下文设计模式
* 线程单例上下文
*
* @author cakin
*/
public class ActionContext {
    private ActionContext() {
    }

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

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

    private static final ThreadLocal<Context> threadLocal = ThreadLocal.withInitial(Context::new);

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

5 线程执行任务

package concurrent.context.improve;

/**
* 线程运行上下文设计模式
* 线程执行任务
*
* @author cakin
*/
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 card id query successful.");
        ActionContext actionContext = ActionContext.getInstance();
        Context context = actionContext.getContext();
        System.out.println("The Name is " + context.getName() + " and CardId is " + context.getCardId());
        System.out.println(context);
    }
}

6 测试用例

package concurrent.context.improve;

import java.util.stream.IntStream;

/**
* 线程运行上下文设计模式
* 上下文测试
*
* @author cakin
*/
public class ContextTest {
    public static void main(String[] args) {
        IntStream.rangeClosed(1, 4).forEach(i -> {
            new Thread(new ExecutionTask(), "T" + i).start();
        });
    }
}

三 测试结果 

The name query successful.

The name query successful.

The name query successful.

The name query successful.

The card id query successful.

The card id query successful.

The card id query successful.

The card id query successful.

The Name is Alex-T2 and CardId is 51082313

The Name is Alex-T3 and CardId is 51082314

The Name is Alex-T4 and CardId is 51082315

concurrent.context.improve.Context@6c3b7d5d

concurrent.context.improve.Context@2bd77d8

The Name is Alex-T1 and CardId is 51082312

concurrent.context.improve.Context@4490a8e8

concurrent.context.improve.Context@af24192

相关文章