被@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,即可继续其他的操作。@Async也可以放在类上,表示整个类的所有方法都是异步的。@Async的唯一参数value的作用是:指定用该执行方法的执行器名称,执行器由我们自己定义的,Executor或者TaskExecutor类型;该参数可为空。
基本用法示例代码:
在需要异步执行的方法加上@Async
@Component
public class SendMessge {
/**
* 异步发送消息方法
*/
@Async
public void send(int message){
String currentThreadName = Thread.currentThread().getName();
System.out.println(currentThreadName + ":" + message);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
然后在应用启动类上加上@EnableAsync
@SpringBootApplication
@EnableAsync
public class TestServerApplication {
public static void main(String[] args) {
SpringApplication.run(TestServerApplication.class, args);
}
}
测试代码
@RunWith(SpringRunner.class)
@SpringBootTest
public class AsyncTest {
@Autowired
private SendMessge sendMessge;
@Test
public void sendTest() throws InterruptedException {
for (int i = 0; i < 5; i++){
sendMessge.send(i);
System.out.println("send message: " +i);
}
Thread.sleep(1000);
}
}
测试结果
send message: 0
send message: 1
send message: 2
send message: 3
send message: 4
SimpleAsyncTaskExecutor-2:1
SimpleAsyncTaskExecutor-5:4
SimpleAsyncTaskExecutor-3:2
SimpleAsyncTaskExecutor-1:0
SimpleAsyncTaskExecutor-4:3
我们也可以自定义用于执行方法的执行器,这样我们能够控制线程池大小,当我们有多个异步方法时,就可以控制每个方法的并发数量。
/**
* 配置SendMessage的异步执行器
*/
@Configuration
@EnableAsync
public class ExecutorConfig {
@Bean
public Executor sendAsyncExecutor() {
//spring的线程池执行器
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(10);
//线程名前缀
executor.setThreadNamePrefix("sendMessage-Thread-");
// 线程池无资源时拒绝新任务的处理策略,CallerRunsPolicy 表示由调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
然后在我们异步方法注解加上参数:@Async("sendAsyncExecutor"),这样就可以了。
上面的异步方法没有返回值,也不能处理异常,如果异步方法需要返回值和异常的处理就下面这样
@Component
public class SendMessge {
/**
* 异步发送消息方法
*/
@Async("sendAsyncExecutor")
public ListenableFuture send(String message) throws InterruptedException {
String currentThreadName = Thread.currentThread().getName();
Thread.sleep(500);
if("error".equals(message)) {
throw new RuntimeException("出错啦");
}else{
System.out.println(currentThreadName + ":" + message);
}
return new AsyncResult<>("send success: " + message);
}
}
测试调用
@RunWith(SpringRunner.class)
@SpringBootTest
public class AsyncTest {
@Autowired
private SendMessge sendMessge;
@Test
public void sendTest() throws ExecutionException, InterruptedException {
ListenableFuture result = sendMessge.send("error");
result.addCallback((Object obj) -> { System.out.println(obj);},
(Throwable ex) -> { System.out.println(ex);});
Thread.sleep(1000);
}
}
测试结果
//正常返回
sendMessage-Thread-1:Hi!
send success: Hi!
//异常返回
java.lang.RuntimeException: 出错啦