SpringBoot的線程調度

Spring Boot默認提供了一個ThreadPoolTaskExecutor作爲線程調度器,只需要在配置類中使用註解EnableAsync即可開啓異步線程調度。在實際要執行的Bean中使用@Async註解來聲明這個方法是異步方法,需要通過線程調度器來執行。

示例代碼如下:

Application類,開啓異步線程調度

Application類,開啓異步線程調度
@SpringBootApplication
@EnableAsync
public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
}

異步任務類,聲明execute()方法通過線程調度器執行

@Service
public class TestAsync {
  
  private static AtomicInteger count = new AtomicInteger(0);

  @Async
  public String execute() {
    System.out.println("begin execute TestAsync: " + count.incrementAndGet());
    try {
      Thread.sleep(10000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println("finished execute TestAsync");
    return "result";
  }
}

要注意的問題:
(1)這裏的@Async註解必須要聲明在Bean對外提供的方法上,如果這個方法不是由其它類直接調用,而是這個類的其它方法間接調用,則不生效。
(2)@Async註解聲明的方法,返回類型要麼聲明爲void,要麼聲明爲Future。因爲方法是異步調用,因此無法立即返回結果,如果聲明爲其它返回類型,則獲取到的是null。聲明爲Future,則可以獲取到任務的執行結果。

Controller類

@RestController
public class TestAsyncController {
  
  @Autowired
  private TestAsync testAsync;
  
  @RequestMapping(value = "/async", method = RequestMethod.GET)
  public String async() {
    System.out.println("before execute TestAsync");
    String result =  testAsync.outexecute();
    System.out.println("after execute TestAsync");
    return result;
  }
}

這裏獲取到的result值null,因此獲取這個返回值沒有什麼意義。

Spring Boot線程調度有以下幾個參數可以配置(2.1版本之後纔有):
spring.task.execution.pool.core-size # 核心線程數,默認爲8
spring.task.execution.pool.queue-capacity # 隊列容量,默認爲無限大
spring.task.execution.pool.max-size # 最大線程數,默認爲無限大
這三個參數的關係如下:
如果當前要執行的任務數超過core-size,則任務會放到隊列裏面等待執行,等核心線程中有任務執行完成之後,再取出隊列中的任務進行調度執行。
如果等待隊列已經滿了,再收到新任務時,則核心線程會自動擴容,最大擴展到max-size。

spring.task.execution.pool.allow-core-thread-timeout # 是否允許回收空閒的線程,默認爲true
spring.task.execution.pool.keep-alive # 空閒的線程可以保留多少秒,默認爲60。如果超過這個時間沒有任務調度,則線程會被回收
spring.task.execution.thread-name-prefix # 線程名前綴,默認爲thread-

自定義線程調度器
如果不想使用Spring Boot自帶的線程調度器,可以通過實現AsyncConfigurer接口來定義自己的線程調度器。
示例代碼如下:

@Configuration
@EnableAsync
public class AppConfig implements AsyncConfigurer {

  @Override
  public Executor getAsyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(7);
    executor.setMaxPoolSize(42);
    executor.setQueueCapacity(11);
    executor.setThreadNamePrefix("MyExecutor-");
    executor.initialize();
    return executor;
  }

  @Override
  public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
    return MyAsyncUncaughtExceptionHandler();
  }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章