异步场景下的ThreadLocal解决方案

2021-04-15 17:37:26 1037

引入依赖

<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>transmittable-thread-local</artifactId>
    <version>2.12.1</version>
</dependency>

线程池配置

@Component
public class AsyncThreadPoolConfiguration implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
        threadPool.setCorePoolSize(5);
        threadPool.setMaxPoolSize(20);
        threadPool.setQueueCapacity(200);
        threadPool.setKeepAliveSeconds(60);
        threadPool.setThreadNamePrefix("MyThread: ");
        threadPool.initialize();
        return TtlExecutors.getTtlExecutor(threadPool);
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return new SimpleAsyncUncaughtExceptionHandler();
    }
}

controller

@RestController
@RequestMapping
public class TestController {

    public static TransmittableThreadLocal<String> VAL = new TransmittableThreadLocal<>();

    @Autowired
    TestService testService;

    @GetMapping("/async")
    public String async() throws ExecutionException, InterruptedException {
        System.out.println("Controller Thread: " + Thread.currentThread().getName());

        VAL.set(new Date().toLocaleString());
        Future<String> test = testService.test();
        test.get();
        System.out.println("------------------------------------");
        return "";
    }
}

service

@Service
public class TestService {

    @Async
    public Future<String> test() {
        try {
            System.out.println("Service Thread: " + Thread.currentThread().getName());
            System.out.println("service get: " + TestController.VAL.get());
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return new AsyncResult<>("yes");
    }

}

输出

Controller Thread: XNIO-1 task-1
Service Thread: MyThread: 1
service get: 2021-4-15 17:35:26
------------------------------------
Controller Thread: XNIO-1 task-1
Service Thread: MyThread: 2
service get: 2021-4-15 17:35:28
------------------------------------
Controller Thread: XNIO-1 task-1
Service Thread: MyThread: 3
service get: 2021-4-15 17:35:30
------------------------------------
Controller Thread: XNIO-1 task-1
Service Thread: MyThread: 4
service get: 2021-4-15 17:35:31
------------------------------------
Controller Thread: XNIO-1 task-1
Service Thread: MyThread: 5
service get: 2021-4-15 17:35:33
------------------------------------
Controller Thread: XNIO-1 task-1
Service Thread: MyThread: 1
service get: 2021-4-15 17:35:34
------------------------------------
Controller Thread: XNIO-1 task-1
Service Thread: MyThread: 2
service get: 2021-4-15 17:35:38
------------------------------------

原理:

装饰者模式

对Runnable进行包装

装饰者模式

浅谈ThreadLocal

ThreadLocal是为了避免共享, 避免锁竞争, 使用了空间换时间的思路若使用Map, Thread做Key, 则回到了问题本身, 仍会发生锁竞争, 降低效率所以数据实际上是存储在java.lang.Thread#threadLocals的 ThreadLocal相当于一个钥匙/桥梁去访问Thr
2022-11-28

异步场景下的ThreadLocal解决方案

引入依赖<dependency> <groupId>com.alibaba</groupId> <artifactId>transmittable-thread-local</artifactId> <version>2.12.1</version> </dependency
2021-04-15

各平台时间格式

javayyyy-MM-dd HH:mm:ss2021-01-18 13:05:25mysqlDATE_FORMAT(time,'%Y-%m-%d %H:%i:%s')2021-01-18 13:05:25sql serverSELECT CONVERT(varchar(100), GETDATE(
2021-01-18

Java 获取当前方法的被调用信息

Thread.currentThread().getStackTrace();
2021-01-28

异步场景下的ThreadLocal解决方案

引入依赖<dependency> <groupId>com.alibaba</groupId> <artifactId>transmittable-thread-local</artifactId> <version>2.12.1</version> </dependency
2021-04-15

Redis缓存更新修改原有值但是不修改失效时间

第一种方式redisTemplate.opsForValue().set("key", "value", 0);第二种方式redisTemplate.opsForValue().increment("key", 1);
2021-04-17

Visual Studio 2019 文件编码问题

Visual Studio 对 utf-8 的支持相当差.cpp/.h 文件先调出高级保存选项菜单, 具体百度设置文件字符编码为utf-8还不够, 还要在项目 => 属性 => C/C++ => 所有选项 => 附加选项 中 设置 /utf-8.rc 文件默认编码gbk, 加了特殊字符无法显示然后改
2021-07-18

屏蔽Postman自动更新

hosts文件添加127.0.0.1 dl.pstmn.io 127.0.0.1 sentry-app.postmanlabs.com
2021-12-23

Nginx相关命令

查看Nginx的版本号:nginx -V 启动Nginx:start nginx 或者 nginx 快速停止或关闭Nginx:nginx -s stop 正常停止或关闭Nginx:nginx -s quit 配置文件修改重装载命令:nginx -s reload 查看windows
2021-12-24
IDEA方法注释模板

IDEA方法注释模板

设置tab键触发注释模板内容** * <p>$methodName$</p> *$param$ $return$ * @Title $methodName$ * @author kyaa * @date $date$ $time$ */ 变量填充param自己脚本模拟def result
2022-01-06

MyBatis-Plus部分方法封装

在此仅记录一种思路public interface SuperMapper<T> extends BaseMapper<T> { default List<T> idNotInList(List<?> idList) { return selectList(new Quer
2022-01-29