Spring異步註解—@Async

被@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: 出錯啦
相關文章
相關標籤/搜索