1. @Async源码探究

1.1. 上代码

  1. @SpringBootApplication
  2. @EnableAsync
  3. public class SpringbootLearnApplication {
  4. public static void main(String[] args) {
  5. SpringApplication.run(SpringbootLearnApplication.class, args);
  6. }
  7. }
  1. @Service
  2. public class CreatingThread08Service {
  3. @Async
  4. public void call(CountDownLatch countDownLatch) {
  5. try {
  6. Thread.sleep(1000);
  7. } catch (InterruptedException e) {
  8. e.printStackTrace();
  9. }
  10. System.out.println(Thread.currentThread().getName() + " is running");
  11. countDownLatch.countDown();
  12. System.out.println(Thread.currentThread().getName() + " is over");
  13. }
  14. }
  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest
  3. public class SpringbootLearnApplicationTests {
  4. @Autowired
  5. private CreatingThread08Service creatingThread08Service;
  6. private int count = 4;
  7. private CountDownLatch countDownLatch = new CountDownLatch(count);
  8. @Test
  9. public void contextLoads() {
  10. StopWatch stopwatch = new StopWatch("async test");
  11. stopwatch.start();
  12. for (int i = 0; i < count; i++) {
  13. creatingThread08Service.call(countDownLatch);
  14. }
  15. try {
  16. countDownLatch.await();
  17. } catch (InterruptedException e) {
  18. e.printStackTrace();
  19. }
  20. stopwatch.stop();
  21. System.out.println(stopwatch.prettyPrint());
  22. }
  23. }

结果

  1. task-2 is running
  2. task-2 is over
  3. task-4 is running
  4. task-4 is over
  5. task-1 is running
  6. task-1 is over
  7. task-3 is running
  8. task-3 is over
  9. StopWatch 'async test': running time (millis) = 1018
  10. -----------------------------------------
  11. ms % Task name
  12. -----------------------------------------
  13. 01018 100%

1.2. 提问

1.2.1. 加了该注解的方法,如果同时被调用n次,难道会创建n个线程?

  • 通过debugger源码找到如下信息,为它默认线程池设置属性

  • 我们把运行数量加大到count=20

  • 结果

  1. task-1 is running
  2. task-1 is over
  3. task-8 is running
  4. task-8 is over
  5. task-5 is running
  6. task-5 is over
  7. task-3 is running
  8. task-3 is over
  9. task-4 is running
  10. task-4 is over
  11. task-7 is running
  12. task-7 is over
  13. task-2 is running
  14. task-2 is over
  15. task-6 is running
  16. task-6 is over
  17. task-1 is running
  18. task-1 is over
  19. task-8 is running
  20. task-3 is running
  21. task-3 is over
  22. task-5 is running
  23. task-5 is over
  24. task-8 is over
  25. task-4 is running
  26. task-6 is running
  27. task-6 is over
  28. task-7 is running
  29. task-7 is over
  30. task-2 is running
  31. task-2 is over
  32. task-4 is over
  33. task-5 is running
  34. task-1 is running
  35. task-8 is running
  36. task-8 is over
  37. task-1 is over
  38. task-3 is running
  39. task-3 is over
  40. task-5 is over
  41. StopWatch 'async test': running time (millis) = 3021
  42. -----------------------------------------
  43. ms % Task name
  44. -----------------------------------------
  45. 03021 100%
  • 可以看出,如截图一致,它的运行核心执行线程数为8,且队列数很大,所以几乎不会再创建新的线程数,我特意sleep了1秒,20个任务,足够该线程池运行3遍,所以最大延迟3秒多

1.3. 那么核心线程数这个值能够变吗?

  • 可以,通过application.properties中修改spring.task.execution.pool.core-size=20的值,比如我现在改成20,那么打印结果如下
  1. task-1 is running
  2. task-9 is running
  3. task-12 is running
  4. task-15 is running
  5. task-17 is running
  6. task-11 is running
  7. task-11 is over
  8. task-1 is over
  9. task-10 is running
  10. task-10 is over
  11. task-8 is running
  12. task-8 is over
  13. task-6 is running
  14. task-6 is over
  15. task-4 is running
  16. task-4 is over
  17. task-7 is running
  18. task-7 is over
  19. task-5 is running
  20. task-3 is running
  21. task-3 is over
  22. task-20 is running
  23. task-20 is over
  24. task-17 is over
  25. task-19 is running
  26. task-19 is over
  27. task-2 is running
  28. task-2 is over
  29. task-18 is running
  30. task-18 is over
  31. task-15 is over
  32. task-16 is running
  33. task-16 is over
  34. task-12 is over
  35. task-14 is running
  36. task-14 is over
  37. task-13 is running
  38. task-13 is over
  39. task-9 is over
  40. task-5 is over
  41. StopWatch 'async test': running time (millis) = 1020
  42. -----------------------------------------
  43. ms % Task name
  44. -----------------------------------------
  45. 01020 100%
  • 所有线程只执行一遍,最大延迟就1秒多了

1.4. 总结

  • 使用该注解,会创建默认核心线程为8的线程池,它的很多属性是可以通过配置设置的,如下
  1. spring.task.execution.pool.core-size=10
  2. spring.task.execution.thread-name-prefix=mytask-
  3. spring.task.execution.pool.queue-capacity=10
  4. spring.task.execution.pool.max-size=20
  5. spring.task.execution.pool.keep-alive=60s
  6. spring.task.execution.pool.allow-core-thread-timeout=true
  • 根据业务需求设置合理的属性值,就相当于spring给你创建了线程池了

@Async源码探究的更多相关文章

  1. spring-cloud-sleuth+zipkin源码探究

    1. spring-cloud-sleuth+zipkin源码探究 1.1. 前言   粗略看了下spring cloud sleuth core源码,发现内容真的有点多,它支持了很多类型的链路追踪, ...

  2. spring-boot-2.0.3之quartz集成,数据源问题,源码探究

    前言 开心一刻 着火了,他报警说:119吗,我家发生火灾了. 119问:在哪里? 他说:在我家. 119问:具体点. 他说:在我家的厨房里. 119问:我说你现在的位置. 他说:我趴在桌子底下. 11 ...

  3. 【转载】Spring @Async 源码解读。

    由于工作中经常需要使用到异步操作,一直在使用@Async, 今天抽空学习了一下它的执行原理,刚好看到一篇写的很棒的文章,这里转载过来做个记录,感谢原作者的无私奉献. 原文章链接地址:https://w ...

  4. Vue源码探究-全局API

    Vue源码探究-全局API 本篇代码位于vue/src/core/global-api/ Vue暴露了一些全局API来强化功能开发,API的使用示例官网上都有说明,无需多言.这里主要来看一下全局API ...

  5. Vue源码探究-事件系统

    Vue源码探究-事件系统 本篇代码位于vue/src/core/instance/events.js 紧跟着生命周期之后的就是继续初始化事件相关的属性和方法.整个事件系统的代码相对其他模块来说非常简短 ...

  6. Vue源码探究-状态初始化

    Vue源码探究-状态初始化 Vue源码探究-源码文件组织 Vue源码探究-虚拟DOM的渲染 本篇代码位于vue/src/core/instance/state.js 继续随着核心类的初始化展开探索其他 ...

  7. Vue源码探究-源码文件组织

    Vue源码探究-源码文件组织 源码探究基于最新开发分支,当前发布版本为v2.5.17-beta.0 Vue 2.0版本的大整改不仅在于使用功能上的优化和调整,整个代码库也发生了天翻地覆的重组.可见随着 ...

  8. SpringBoot读取配置文件源码探究

    1. SpringBoot读取配置文件源码探究 1.1. 概览 springboot的源码是再原来的Spring源码上又包了一层,看过spring源码都知道,当我们从入口debug进去的时候,原来的S ...

  9. Sharding-Jdbc源码探究-读写分离

    1. Sharding-Jdbc源码探究-读写分离 1.1. 主入口 找到源码入口 这一个类围绕了springboot配置属性的加载,加载了spring.shardingsphere.datasour ...

随机推荐

  1. EditPlus常用正则表达式

    正则表达式(Regular Expression,在代码中常简写为regex.regexp或RE)是计算机科学的一个概念.正则表达式使用单个字符串来描述.匹配一系列符合某个句法规则的字符串.在很多文本 ...

  2. 面向对象程序设计(java)

    201871010136-赵艳强<面向对象程序设计(java)>第二周学习总   第一部分:理论知识学习部分 一.简单的Java程序应运程序 1.标识符0标识符由字母.下划线.美元符号和数 ...

  3. [RN] React Native FlatList 选中后 状态没有立即发生改变,而在下一次生效的问题

    React Native FlatList 选中后 状态没有立即发生改变,而在下一次生效的问题 解决关键: 给 FlatList 添加 extraData={this.state} 非常关键,如果不设 ...

  4. MySQL实战45讲学习笔记:第二十三讲

    一.本节概要 今天这篇文章,我会继续和你介绍在业务高峰期临时提升性能的方法.从文章标题“MySQL 是怎么保证数据不丢的?”,你就可以看出来,今天我和你介绍的方法,跟数据的可靠性有关. 在专栏前面文章 ...

  5. WPF 目录树绑定 与 遍历

    定义树节点,(编译环境VS2017) public class GBTreeNode : INotifyPropertyChanged { private string _deviceId = str ...

  6. netcat 传输T级别大文件

    接收端 nc -d -l 5002 |tar xf - nohup  sh receive.sh  &   发送端 tar cf - . | nc  1.1.1.1  5002 nohup   ...

  7. 第五次实验报告:使用Packet Tracer理解OSPF路由协议

    目录 1 实验目的 2 实验内容 3. 实验报告 3.1 建立网络拓扑结构 4. 配置 4.1 配置并激活串行地址和以太网地址 4.1.1 R1 4.1.2 R2 4.1.3 R3 4.1.4 PC ...

  8. 小i机器人

    //机器人回复 function xiaoirobot($openid, $content) { //定义app $app_key = ""; $app_secret = &quo ...

  9. 深入理解C语言 - 指针详解

    一.什么是指针 C语言里,变量存放在内存中,而内存其实就是一组有序字节组成的数组,每个字节有唯一的内存地址.CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位.这里,数据对象是指存储在 ...

  10. 调用其他python脚本文件里面的类和方法

    问题描述: 自己编写了若干个Python脚本. 在testC.py里面需要调用testA.py和testB.py里面的若干类和方法.要怎么办? 需要都打包.安装,再去调用吗? 其实不必那么麻烦. 这里 ...