zoukankan      html  css  js  c++  java
  • SpringBoot的线程调度

    Spring Boot默认提供了一个ThreadPoolTaskExecutor作为线程调度器,只需要在配置类中使用注解EnableAsync即可开启异步线程调度。在实际要执行的Bean中使用@Async注解来声明这个方法是异步方法,需要通过线程调度器来执行。

    示例代码如下:

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

      

  • 相关阅读:
    第二章 金字塔内部的结构
    第一章 为什么要用金字塔结构
    考研级《计算机网络》知识梳理——第二期
    考研级《计算机网络》知识梳理——第一期
    leetcode常规算法题复盘(科普短文篇)——为何哈希表的容量一般是质数
    leetcode常规算法题复盘(第十六期)——数据流中的第 K 大元素
    leetcode常规算法题复盘(第十四期)——最后一块石头的重量
    leetcode常规算法题复盘(第十三期)——最大矩形&柱状图中最大的矩形
    leetcode常规算法题复盘(第十二期)——摆动序列&买卖股票的最佳时机含手续费
    leetcode常规算法题复盘(基础篇)——线性表java实现
  • 原文地址:https://www.cnblogs.com/lasdaybg/p/10161249.html
Copyright © 2011-2022 走看看