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();
  }
}

 

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