• @Async源码探究


    1. @Async源码探究

    1.1. 上代码

    @SpringBootApplication
    @EnableAsync
    public class SpringbootLearnApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringbootLearnApplication.class, args);
        }
    
    }
    
    @Service
    public class CreatingThread08Service {
    
        @Async
        public void call(CountDownLatch countDownLatch) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " is running");
            countDownLatch.countDown();
            System.out.println(Thread.currentThread().getName() + " is over");
    
        }
    }
    
    
    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class SpringbootLearnApplicationTests {
    
        @Autowired
        private CreatingThread08Service creatingThread08Service;
    
        private int count = 4;
    
        private CountDownLatch countDownLatch = new CountDownLatch(count);
    
        @Test
        public void contextLoads() {
    
            StopWatch stopwatch = new StopWatch("async test");
            stopwatch.start();
            for (int i = 0; i < count; i++) {
                creatingThread08Service.call(countDownLatch);
            }
            try {
                countDownLatch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            stopwatch.stop();
            System.out.println(stopwatch.prettyPrint());
        }
    
    }
    
    

    结果

    task-2 is running
    task-2 is over
    task-4 is running
    task-4 is over
    task-1 is running
    task-1 is over
    task-3 is running
    task-3 is over
    StopWatch 'async test': running time (millis) = 1018
    -----------------------------------------
    ms     %     Task name
    -----------------------------------------
    01018  100%  
    
    

    1.2. 提问

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

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

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

    • 结果

    task-1 is running
    task-1 is over
    task-8 is running
    task-8 is over
    task-5 is running
    task-5 is over
    task-3 is running
    task-3 is over
    task-4 is running
    task-4 is over
    task-7 is running
    task-7 is over
    task-2 is running
    task-2 is over
    task-6 is running
    task-6 is over
    task-1 is running
    task-1 is over
    task-8 is running
    task-3 is running
    task-3 is over
    task-5 is running
    task-5 is over
    task-8 is over
    task-4 is running
    task-6 is running
    task-6 is over
    task-7 is running
    task-7 is over
    task-2 is running
    task-2 is over
    task-4 is over
    task-5 is running
    task-1 is running
    task-8 is running
    task-8 is over
    task-1 is over
    task-3 is running
    task-3 is over
    task-5 is over
    StopWatch 'async test': running time (millis) = 3021
    -----------------------------------------
    ms     %     Task name
    -----------------------------------------
    03021  100%  
    
    • 可以看出,如截图一致,它的运行核心执行线程数为8,且队列数很大,所以几乎不会再创建新的线程数,我特意sleep了1秒,20个任务,足够该线程池运行3遍,所以最大延迟3秒多

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

    • 可以,通过application.properties中修改spring.task.execution.pool.core-size=20的值,比如我现在改成20,那么打印结果如下
    task-1 is running
    task-9 is running
    task-12 is running
    task-15 is running
    task-17 is running
    task-11 is running
    task-11 is over
    task-1 is over
    task-10 is running
    task-10 is over
    task-8 is running
    task-8 is over
    task-6 is running
    task-6 is over
    task-4 is running
    task-4 is over
    task-7 is running
    task-7 is over
    task-5 is running
    task-3 is running
    task-3 is over
    task-20 is running
    task-20 is over
    task-17 is over
    task-19 is running
    task-19 is over
    task-2 is running
    task-2 is over
    task-18 is running
    task-18 is over
    task-15 is over
    task-16 is running
    task-16 is over
    task-12 is over
    task-14 is running
    task-14 is over
    task-13 is running
    task-13 is over
    task-9 is over
    task-5 is over
    StopWatch 'async test': running time (millis) = 1020
    -----------------------------------------
    ms     %     Task name
    -----------------------------------------
    01020  100%  
    
    • 所有线程只执行一遍,最大延迟就1秒多了

    1.4. 总结

    • 使用该注解,会创建默认核心线程为8的线程池,它的很多属性是可以通过配置设置的,如下
    spring.task.execution.pool.core-size=10
    spring.task.execution.thread-name-prefix=mytask-
    spring.task.execution.pool.queue-capacity=10
    spring.task.execution.pool.max-size=20
    spring.task.execution.pool.keep-alive=60s
    spring.task.execution.pool.allow-core-thread-timeout=true
    
    • 根据业务需求设置合理的属性值,就相当于spring给你创建了线程池了
  • 相关阅读:
    网络流
    Link-Cut-Tree题集
    动态点分治
    斜率优化DP
    【Python学习之旅】---继承的方式完成包装(授权、item系列、str&repr、format 自定义格式方法)
    【Python学习之旅】---动态导入模块
    【Python学习之旅】---封装与反射(类的相关知识,面向对象三大特性:继承-多态-封装)
    【Python学习之旅】---多态(类的相关知识,面向对象三大特性:继承-多态-封装)
    【Python学习之旅】---多态(类的相关知识)
    【Python学习之旅】---继承(类的相关知识)
  • 原文地址:https://www.cnblogs.com/sky-chen/p/11635875.html
Copyright © 2020-2023  润新知