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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/vbirdbest/article/details/82346655

一:简介

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) { }
        }
    }
}

这里写图片描述

这里写图片描述

猜你喜欢

转载自blog.csdn.net/vbirdbest/article/details/82346655