Spring Boot使用ThreadLocal、Inherit

2019-05-27  本文已影响0人  CallMe兵哥

简介

首先说一下这三者之间的区别:

至于这三个类的源码分析,网上很多,我们这里暂时不说。下面给大家简单介绍下在WEB项目里面,这三个类的具体使用情况。

1. 同步情况下ThreadLocal的表现

1)首先引入依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

2)建立Service层代码
先生成接口类

public interface PiceaService {
    //测试ThreadLocal方法
    String testThreadLocal() throws Exception;
}

然后完成实现

@Service
public class PiceaServiceImpl implements PiceaService {
    @Override
    public String testThreadLocal() throws Exception {
        System.out.println("我是Service层处理线程,线程名:" + Thread.currentThread().getName());
        System.out.println(" ThreadLocalUtil保存的值为:" + ThreadLocalUtil.getValue());
        ThreadLocalUtil.remove();
        return "sss";
    }
}

3)建立Controller层代码

@RestController
public class PiceaContoller {

    @Autowired
    private PiceaService piceaService;

    @RequestMapping("/testTl")
    public String testThreadLocal() throws Exception {
        System.out.println("我是Controller层处理线程,线程名:" + Thread.currentThread().getName());
        ThreadLocalUtil.setValue("我是:testThreadLocal");
        System.out.println("这里是处理过程,处理中.........");
        System.out.println(" ThreadLocalUtil保存的值为:" + ThreadLocalUtil.getValue());
        String ret = piceaService.testThreadLocal();
        return "testThreadLocal:" + ret;
    }
}

4)测试结果
浏览器中输入http://localhost:2001/testTl
从图片中可以看出,设置的值无论是在Controller层,还是Service层,都很顺利。

Spring-boot-TL-TL.png

2. 异步情况下ThreadLocal的表现

同步的情况下,ThreadLocal表现还可以,在各个层之间使用都很正常,下面我们改成异步的看看效果。
1)增加异步配置
在启动类中,增加开启异步支持,增加注解"@EnableAsync"。

@EnableAsync
@SpringBootApplication
public class SpringBootInheritablethreadlocalApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringBootInheritablethreadlocalApplication.class, args);
    }
}

2)在Service层增加方法
先增加接口

void testThreadLocalAsync() throws Exception;

然后增加实现

    @Async
    @Override
    public void testThreadLocalAsync() throws Exception {
        System.out.println("我是Service层处理线程,线程名:" + Thread.currentThread().getName());
        System.out.println(" ThreadLocalUtil保存的值为:" + ThreadLocalUtil.getValue());
        ThreadLocalUtil.remove();
    }

3)在Controller层增加测试方法

    @RequestMapping("/testTlA")
    public String testThreadLocalAsync() throws Exception {
        System.out.println("我是Controller层处理线程,线程名:" + Thread.currentThread().getName());
        ThreadLocalUtil.setValue("我是:testThreadLocalAsync");
        System.out.println("这里是处理过程,处理中.........");
        System.out.println(" ThreadLocalUtil保存的值为:" + ThreadLocalUtil.getValue());
        piceaService.testThreadLocalAsync();
        return "testThreadLocalAsync:";
    }

4)测试结果
浏览器中输入http://localhost:2001/testTlA
在结果中,可以发现Service层无法取得父线程设置的值。

Spring-boot-TL-TLA.png

3. 异步情况下InheritableThreadLocal的表现

在异步的情况下,ThreadLocal已经取不到父线程的值,现在我们是要它的升级类InheritableThreadLocal看看效果。
1)在Service层增加方法
先增加接口

void testThreadLocalAsyncItl() throws Exception;

然后增加实现

    @Async
    @Override
    public void testThreadLocalAsyncItl() throws Exception {
        System.out.println("我是Service层处理线程,线程名:" + Thread.currentThread().getName());
        System.out.println(" InheritableThreadLocalUtil保存的值为:" + InheritableThreadLocalUtil.getValue());
        InheritableThreadLocalUtil.remove();
    }

3)在Controller层增加测试方法

    @RequestMapping("/testItl")
    public String testInheritableThreadLocal() throws Exception {
        System.out.println("我是Controller层处理线程,线程名:" + Thread.currentThread().getName());
        InheritableThreadLocalUtil.setValue("我是:testInheritableThreadLocal");
        System.out.println("这里是处理过程,处理中.........");
        System.out.println(" InheritableThreadLocalUtil保存的值为:" + InheritableThreadLocalUtil.getValue());
        piceaService.testThreadLocalAsyncItl();
        return "testInheritableThreadLocal:";
    }

4)测试结果
浏览器中输入http://localhost:2001/testItlTl
在结果中,可以看到Service层可以正常取得父线程设置的值。

Spring-boot-TL-ITL.png

第二章节请移步
Spring Boot使用ThreadLocal、InheritableThreadLocal、TransmittableThreadLocal -2

其它注意

本文章样例:
工程名:spring-boot-inheritablethreadlocal
GitHub:https://github.com/zzyjb/SpringBootLearning

关于异步服务和线程池请移步

  1. Spring Boot 之异步Web服务
上一篇 下一篇

猜你喜欢

热点阅读