被@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: 出錯啦