1. 程式人生 > >Spring Boot入門教程(四十六): @Async

Spring Boot入門教程(四十六): @Async

一:簡介

ThreadPoolTaskExecutor 用於定義執行緒池,是對java.util.concurrent.ThreadPoolExecutor類的包裝。可以通過@EnableAsync來開啟非同步支援,通過@Async來宣告一個非同步方法

二:示例

@Configuration
@EnableAsync
public class AsyncConfiguration implements AsyncConfigurer {

    /**
     * 定義執行緒池
     * @return
     */
    @Override
    public
Executor getAsyncExecutor() { ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); taskExecutor.setCorePoolSize(5); taskExecutor.setMaxPoolSize(10); taskExecutor.setQueueCapacity(25); taskExecutor.initialize(); return taskExecutor; } /** * 非同步方法丟擲異常時處理器 * return null: 使用預設的處理器,列印異常資訊和堆疊 * 也可以自定義自己的異常處理器 * @return
*/
@Override public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { return null; // return new MyAsyncUncaughtExceptionHandler(); } /** * 自定義異常處理 * 沒有返回值的非同步方法當拋異常時會走AsyncUncaughtExceptionHandler */ class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler { @Override
public void handleUncaughtException(Throwable throwable, Method method, Object... objects) { System.out.println("Exception message - " + throwable.getMessage()); System.out.println("Method name - " + method.getName()); for (Object param : objects) { System.out.println("Parameter value - " + param); } } } }

注意:非同步方法的呼叫和非同步方法的宣告必須不能在同一個類中,如果在同一個類中則變成了同步方法

@Service
public class AsyncTaskService {

    /**
     * 無參無返回值
     */
    @Async
    public void executeAsyncTask1() {
        for (int i = 0; i < 5; i++) {
            System.out.println("executeAsyncTask1 = " + Thread.currentThread().getName() + "\t i=" + i);
            try {
                Thread.sleep(100);
                // int a = 1/0;
            } catch (InterruptedException e) { }
        }
    }

    /**
     * 有參無返回值
     * @param name
     */
    @Async
    public void executeAsyncTask2(String name) {
        for (int i = 0; i < 5; i++) {
            System.out.println(name + " =\t" + Thread.currentThread().getName() + "\t i=" + i);
            try { Thread.sleep(100); } catch (InterruptedException e) { }
        }
    }

    /**
     * 有返回值有引數
     * 這種情況下當方法拋異常可以在方法內部處理掉異常或者在呼叫future.get時處理異常
     * @param value
     * @return
     */
    @Async
    public Future<String> executeAsyncTask3(String value) {
        Future<String> future;
        try {
            Thread.sleep(100);
            System.out.println(value + " =\t" + Thread.currentThread().getName());
            future = new AsyncResult<>(value.toUpperCase());
        } catch (InterruptedException e) {
            future = new AsyncResult<String>("error");
        }
        return future;
    }
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootAsyncApplicationTests {

    @Autowired
    private AsyncTaskService asyncTaskService;

    @Test
    public void testAsync() throws Exception {
        asyncTaskService.executeAsyncTask1();
        asyncTaskService.executeAsyncTask2("AsyncTask2");
        Future<String> future = asyncTaskService.executeAsyncTask3("AsyncTask3");
        String result = future.get();
        System.out.println("result=" + result);

        Thread.sleep(3000);
    }

    @Test
    public void testSync() throws Exception {
        test();
        for (int i = 0; i < 10; i++) {
            System.out.println("testSync = " + Thread.currentThread().getName() + "\t i=" + i);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) { }
        }
        Thread.sleep(3000);
    }

    /**
     * 注意:@Async要想非同步,呼叫方法的程式碼和方法的宣告必須在不同的類中才能非同步,否則是同步
     * test(); 方法的呼叫在SpringbootAsyncApplicationTests這個類,方法的宣告也是在這個類,所以該方法實際是同步方法,並不是非同步
     */
    @Async
    public void test() {
        for (int i = 0; i < 10; i++) {
            System.out.println("SpringbootAsyncApplicationTests = " + Thread.currentThread().getName() + "\t i=" + i);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) { }
        }
    }
}

這裡寫圖片描述

這裡寫圖片描述