pom
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
springboot启动异步任务需要在启动类加上@EnableAsync注解, 在方法或类上加上@Async
注意:在同一类中,不能在一个方法中调用另一个异步方法
Task
package com.dev.async.async;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import java.util.concurrent.Future;
/**
* @Async
* 注解放在类上,该类所有方法异步执行
* 注解放在方法上,该方法异步执行
*/
@Async
@Component
public class Task {
public void run1(){
System.out.println("任务一");
}
public void run2(){
System.out.println("任务二");
}
public void run3(){
System.out.println("任务三");
}
public Future<String> run4(){
System.out.println("任务四");
return new AsyncResult<String>("执行成功!");
}
public Future<Integer> run5(){
System.out.println("任务五");
return new AsyncResult<Integer>(0);
}
public Future<Boolean> run6(){
System.out.println("任务六");
return new AsyncResult<Boolean>(true);
}
}
@EnableAsync
package com.dev.async;
import com.dev.async.async.Task;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@SpringBootApplication
@RestController
@EnableAsync
public class AsyncApplication {
@Autowired
private Task task;
public static void main(String[] args) {
SpringApplication.run(AsyncApplication.class, args);
}
@PostMapping("/run")
public void index() throws ExecutionException, InterruptedException {
task.run1();
task.run2();
task.run3();
Future<String> stringFuture = task.run4();
Future<Integer> integerFuture = task.run5();
Future<Boolean> booleanFuture = task.run6();
for (;;){
if (stringFuture.isDone() && integerFuture.isDone() && booleanFuture.isDone()) {
System.out.println(task.run4().get());
System.out.println(task.run5().get());
System.out.println(task.run6().get());
break;
}
}
}
}
Async对于线程池的选择顺序
有需要也可以增加线程池配置
ThreadPoolConfig
package com.dev.async.async;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* @ClassName : ThreadPoolConfig //类名
* @Description : 线程池配置 //描述
*/
@Configuration
public class ThreadPoolConfig {
@Value("${Thread.MaxPoolSize}")
private Integer MaxPoolSize;
@Value("${Thread.CorePoolSize}")
private Integer CorePoolSize;
@Value("${Thread.QueueCapacity}")
private Integer QueueCapacity;
@Value("${Thread.KeepAliveSeconds}")
private Integer KeepAliveSeconds;
@Value("${Thread.ThreadNamePrefix}")
private String ThreadNamePrefix;
@Bean
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(MaxPoolSize);
executor.setCorePoolSize(CorePoolSize);
executor.setQueueCapacity(QueueCapacity);
executor.setKeepAliveSeconds(KeepAliveSeconds);
executor.setThreadNamePrefix(ThreadNamePrefix);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.setAwaitTerminationSeconds(60);
executor.initialize();
return executor;
}
}
yml
server:
port: 80
servlet:
contest-path: /
spring:
application:
name: springboot-async
#线程池配置
Thread:
#最大容量
MaxPoolSize: 100
#核心线程数
CorePoolSize: 10
#缓冲队列数
QueueCapacity: 100
#允许线程空闲时间(单位:默认为秒)
KeepAliveSeconds: 10
#线程名称前缀
ThreadNamePrefix: task-pool-%d
运行
可以多运行几次,查看效果
可以看出,每次运行的顺序都不相同
Future
Java 1.5开始,提供了Callable和Future,通过它们可以在任务执行完毕之后得到任务执行结果。Future就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果。必要时可以通过get方法获取执行结果,该方法会阻塞直到任务返回结果,如果涉及到需要拿到执行结果,这并不是我们想要的效果
CompletableFuture
CompletableFuture类实现了CompletionStage和Future接口,因此你可以像Future那样使用它。
将Future改为CompletableFuture执行
看来有机会要深入了解下CompletableFuture实现原理了。。。。。。
GitHub:传送门