被@Async标注的方法,称之为异步方法;这些方法将在执行的时候,将会在独立的线程中被执行,调用者无需等待它的完成,便可继续其余的操做。@Async也能够放在类上,表示整个类的全部方法都是异步的。@Async的惟一参数value的做用是:指定用该执行方法的执行器名称,执行器由咱们本身定义的,Executor或者TaskExecutor类型;该参数可为空。java
基本用法示例代码:spring
在须要异步执行的方法加上@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); } }
测试结果.net
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"),这样就能够了。code
上面的异步方法没有返回值,也不能处理异常,若是异步方法须要返回值和异常的处理就下面这样ci
@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: 出错啦