线程上下文的那些事儿

一、背景

在实际代码开发中,有些时候,单个线程执行任务非常多的时候,后一个步输入是前一个步骤的输出,若是一直带着一个参数传递,就会显得很冗余,于是就有了线程上下文的设计,每个线程会有不同的参数实例。

二、实现

ThreadLocal作为一个线程私有化的类,内部有一个私有变量ThreadLocalMap,其已每个线程Thread.currentThread()作为key,这样就可以保证线程的独立性。因此我们可以利用ThreadLocal进行线程上下文的构建。
新建一个上下文的类:

import java.io.Serializable;

/**
 * @author: liulei
 * @date: 2022-04-13 15:42
 **/
public class TestContext {
    private ThreadLocal<Context> threadLocal;

    private TestContext() {
        this.threadLocal = new InheritableThreadLocal<>();
    }

    public void clear() {
        this.threadLocal.remove();
    }

    private static class Singleton {
        private static final TestContext testContext = new TestContext();
    }

    public static TestContext getInstance() {
        return Singleton.testContext;
    }

    public Context getContext() {
        if (threadLocal.get() == null) {
            threadLocal.set(new Context());
        }
        return threadLocal.get();
    }

    public String getName() {
        return getContext().getName();
    }

    public void setName(String name) {
        getContext().setName(name);
    }

    public void setAge(Integer age) {
        getContext().setAge(age);
    }

    public static class Context implements Serializable {
        private String name;
        private Integer age;

        public String getName() {
            return this.name;
        }

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

        public void setAge(Integer age) {
            this.age = age;
        }
    }
}

当我们把在某一个线程中把属性set进上下文中,就可以在该线程的调用链中随取随用。

三、一些问题

这里需要强调一点的是:此处我们threadLocal用的InheritableThreadLocal进行实例化,如果直接是用ThreadLocal类进行实例化,在子线程中是获取不到父线程的上下文的,因此这里需要区别使用。

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        TestContext.getInstance().setName("testName");
        CompletableFuture<Void> future = CompletableFuture.runAsync(()->{
            System.out.println(Thread.currentThread()+" start,time->"+System.currentTimeMillis());
//            TestContext.getInstance().setAge(11);
            System.out.println(Thread.currentThread()+ TestContext.getInstance().getName());
            System.out.println(Thread.currentThread()+" exit,time->"+System.currentTimeMillis());
            TestContext.getInstance().clear();
        });
        System.out.println(Thread.currentThread()+" start,time->"+System.currentTimeMillis());
        //等待子任务执行完成
        future.get();
        System.out.println(Thread.currentThread()+ TestContext.getInstance().getName());
        System.out.println(Thread.currentThread()+" exit,time->"+System.currentTimeMillis());
    }

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值