spring|5年华为架构师1小时把SpringBoot项目并发提升了10倍,网友:牛掰( 三 )


【把这个MyCallable对象的属性context 设置到setRequestAttributes中】 所以在执行具体业务时 , 当前线程(子线程)就能取得主线程的Attributes 。
2、MyThreadPoolTaskExecutor类是继承了ThreadPoolTaskExecutor 重写了submit和submitListenable方法 。
为什么是重写submit和submitListenable这两个方法了?
@Async AOP源码的方法位置是在:AsyncExecutionInterceptor.invoke
doSubmit方法能看出来
无返回值调用的是线程池方法:submit()
有返回值 , 根据不同的返回类型也知道:

  • 返回值类型是:Future.class 调用的是方法:submit()
  • 返回值类型是:ListenableFuture.class 调用的方法是:submitListenable(task)
  • 返回值类型是:CompletableFuture.class调用的是CompletableFuture.supplyAsync这个在异步注解中暂时用不上的 , 就不考虑重写了 。


2、ThreadPoolExecutor 原生线程池
ThreadPoolExecutor线程池代码如下:


像ThreadPoolExecutor主要重写execute方法 , 在启动新线程的时候先把Attributes取到放到MyRunnable对象的一个属性中 , MyRunnable在具体执行run方法的时候 , 把属性Attributes赋值到子线程中 , 当run方法执行完了在把Attributes清空掉 。
为什么只要重写了execute方法就可以了?
ThreadPoolExecutor大家都知道主要是由submit和execute方法来执行的 。
看ThreadPoolExecutor类的submit具体执行方法是由父类AbstractExecutorService#submit来实现 。
具体代码在下面贴出来了 , 可以看到submit实际上最后调用的还是execute方法 , 所以我们重写execute方法就好了 。
submit方法路径及源码:
java.util.concurrent.AbstractExecutorService#submit(java.lang.Runnable)

方案二:(推荐)ThreadPoolTaskExecutor线程池
实现TaskDecorator接口把实现类设置到taskExecutor.setTaskDecorator(new MyTaskDecorator());

为什么设置了setTaskDecorator就能实现透传数据了?
【spring|5年华为架构师1小时把SpringBoot项目并发提升了10倍,网友:牛掰】主要还是看taskExecutor.initialize()方法 , 主要是重写了ThreadPoolExecutor的execute方法 , 用装饰器模式 增强了Runnable接口 , 源代码如下:


总结无论是方案1还是方案2 , 原理都是先在当前线程获取到Attributes , 然后把Attributes赋值到Runnable的一个属性中 , 在起一个子线程后 , 具体执行run方法的时候 , 把Attributes设置给当子线程 , 当run方法执行完了 , 在清空Attributes 。
方案2实现比较优雅 , 所以推荐使用它 。
工作没多久的时候觉得spring的使用很麻烦 , 但是工作久了慢慢发现spring一些小细节、设计模式运用得非常巧妙 , 很容易解决遇到的问题 , 只能说spring厉害 。
今日份分享已结束 , 请大家多多包涵和指点!