Springboot学习笔记(一)-线程池的简化及使用

时间:2023-01-03 02:10:49

工作中经常涉及异步任务,通常是使用多线程技术,比如线程池ThreadPoolExecutor,它的执行规则如下:

Springboot学习笔记(一)-线程池的简化及使用

在Springboot中对其进行了简化处理,只需要配置一个类型为java.util.concurrent.TaskExecutor或其子类的bean,并在配置类或直接在程序入口类上声明注解@EnableAsync

调用也简单,在由Spring管理的对象的方法上标注注解@Async,显式调用即可生效。

一般使用Spring提供的ThreadPoolTaskExecutor类。

声明

@Configuration
@EnableAsync
public class BeanConfig { @Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 设置核心线程数
executor.setCorePoolSize(5);
// 设置最大线程数
executor.setMaxPoolSize(10);
// 设置队列容量
executor.setQueueCapacity(20);
// 设置线程活跃时间(秒)
executor.setKeepAliveSeconds(60);
// 设置默认线程名称
executor.setThreadNamePrefix("hello-");
// 设置拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 等待所有任务结束后再关闭线程池
executor.setWaitForTasksToCompleteOnShutdown(true);
return executor;
}
}

调用

@Component
public class Hello {
@Async
public void sayHello(String name) {
LoggerFactory.getLogger(Hello.class).info(name + ":Hello World!");
}
}

测试

Springboot学习笔记(一)-线程池的简化及使用

从打印日志中可以看出线程池已经正常工作了。

进阶

有时候我们不止希望异步执行任务,还希望任务执行完成后会有一个返回值,在java中提供了Future泛型接口,用来接收任务执行结果,springboot也提供了此类支持,使用实现了ListenableFuture接口的类如AsyncResult来作为返回值的载体。比如上例中,我们希望返回一个类型为String类型的值,可以将返回值改造为:

    @Async
public ListenableFuture<String> sayHello(String name) {
String res = name + ":Hello World!";
LoggerFactory.getLogger(Hello.class).info(res);
return new AsyncResult<>(res);
}

调用返回值:

    @Autowired
private Hello hello; // 阻塞调用
hello.sayHello("yan").get();
// 限时调用
hello.sayHello("yan").get(1, TimeUnit.SECONDS)

补充

  1. 实际上,@Async还有一个参数,通过Bean名称来指定调用的线程池-比如上例中设置的线程池参数不满足业务需求,可以另外定义合适的线程池,调用时指明使用这个线程池-缺省时springboot会优先使用名称为'taskExecutor'的线程池,如果没有找到,才会使用其他类型为TaskExecutor或其子类的线程池。
  2. 个人觉得这篇文章还不错:https://www.cnblogs.com/zedosu/p/6665306.html