Spring Boot 自定义线程池使用@Async实现异步调用任务
2021-04-21 15:29
标签:直接 lse keepaliv etc join 表示 设置 ring header 第一步,先在Spring Boot主类中定义一个线程池,比如: 上面我们通过使用 在定义了线程池之后,我们如何让异步调用的执行任务使用这个线程池中的资源来运行呢?方法非常简单,我们只需要在 执行上面的单元测试,我们可以在控制台中看到所有输出的线程名前都是之前我们定义的线程池前缀名开始的,说明我们使用线程池来执行异步任务的试验成功了! 异步方法里按照平时那样返回结果,主线程是获取不到的; Future提供了三种功能: 判断任务是否完成; 能够中断任务; 能够获取任务执行结果 它的接口定义如下: 它声明这样的五个方法: cancel方法用来取消任务,如果取消任务成功则返回true,如果取消任务失败则返回false。参数mayInterruptIfRunning表示是否允许取消正在执行却没有执行完毕的任务,如果设置true,则表示可以取消正在执行过程中的任务。如果任务已经完成,则无论mayInterruptIfRunning为true还是false,此方法肯定返回false,即如果取消已经完成的任务会返回false;如果任务正在执行,若mayInterruptIfRunning设置为true,则返回true,若mayInterruptIfRunning设置为false,则返回false;如果任务还没有执行,则无论mayInterruptIfRunning为true还是false,肯定返回true。 isCancelled方法表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。 isDone方法表示任务是否已经完成,若任务完成,则返回true; get()方法用来获取执行结果,这个方法会产生阻塞主线程,会一直等到任务执行完毕才返回; get(long timeout, TimeUnit unit)用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null。 如果是用循环跑了多个任务,想要等待多个异步任务都结束,主线程才结束,可以这样写 Spring Boot 自定义线程池使用@Async实现异步调用任务 标签:直接 lse keepaliv etc join 表示 设置 ring header 原文地址:https://www.cnblogs.com/SmallStrange/p/13280540.html定义线程池
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@EnableAsync
@Configuration
class TaskPoolConfig {
@Bean("taskExecutor")
public Executor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(200);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("taskExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
}
}
ThreadPoolTaskExecutor
创建了一个线程池,同时设置了以下这些参数:
CallerRunsPolicy
策略,当线程池没有处理能力的时候,该策略会直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务使用线程池
@Async
注解中指定线程池名即可,比如:@Slf4j
@Component
public class Task {
public static Random random = new Random();
@Async("taskExecutor")
public void doTaskOne() throws Exception {
log.info("开始做任务一");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务一,耗时:" + (end - start) + "毫秒");
}
@Async("taskExecutor")
public void doTaskTwo() throws Exception {
log.info("开始做任务二");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务二,耗时:" + (end - start) + "毫秒");
}
@Async("taskExecutor")
public void doTaskThree() throws Exception {
log.info("开始做任务三");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务三,耗时:" + (end - start) + "毫秒");
}
}
单元测试
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class ApplicationTests {
@Autowired
private Task task;
@Test
public void test() throws Exception {
task.doTaskOne();
task.doTaskTwo();
task.doTaskThree();
Thread.currentThread().join();
}
}
2020-03-27 22:01:15.620 INFO 73703 --- [ taskExecutor-1] com.didispace.async.Task : 开始做任务一
2020-03-27 22:01:15.620 INFO 73703 --- [ taskExecutor-2] com.didispace.async.Task : 开始做任务二
2020-03-27 22:01:15.620 INFO 73703 --- [ taskExecutor-3] com.didispace.async.Task : 开始做任务三
2020-03-27 22:01:18.165 INFO 73703 --- [ taskExecutor-2] com.didispace.async.Task : 完成任务二,耗时:2545毫秒
2020-03-27 22:01:22.149 INFO 73703 --- [ taskExecutor-3] com.didispace.async.Task : 完成任务三,耗时:6529毫秒
2020-03-27 22:01:23.912 INFO 73703 --- [ taskExecutor-1] com.didispace.async.Task : 完成任务一,耗时:8292毫秒
注意,方法标记了@Async 调用该方法,不能在该类中调用,不然不管用,就是调用者和被调用者不能是用一个类;
Future
类型Future的get
方法可以阻塞主线程,直到子线程执行完毕,获取异步结果;
@Async("taskExecutor")
public Future
public interface Future
List
文章标题:Spring Boot 自定义线程池使用@Async实现异步调用任务
文章链接:http://soscw.com/index.php/essay/77668.html