欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

@Async源码探究

程序员文章站 2022-04-14 20:45:22
1. 源码探究 1.1. 上代码 @RunWith(SpringRunner.class) @SpringBootTest public class SpringbootLearnApplicationTests { @Autowired private CreatingThread08Servic ......

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源码找到如下信息,为它默认线程池设置属性
    @Async源码探究

  • 我们把运行数量加大到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给你创建了线程池了