zoukankan      html  css  js  c++  java
  • Spring @Async开启异步任务

    1. 开启异步

    @SpringBootApplication
    @EnableAsync        //开启异步任务
    public class Application {
        @Bean(name="processExecutor")
        public TaskExecutor workExecutor() {
            ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
            threadPoolTaskExecutor.setThreadNamePrefix("Async-");
            threadPoolTaskExecutor.setCorePoolSize(10);
            threadPoolTaskExecutor.setMaxPoolSize(20);
            threadPoolTaskExecutor.setQueueCapacity(600);
            threadPoolTaskExecutor.afterPropertiesSet();
    
            // 自定义拒绝策略
            threadPoolTaskExecutor.setRejectedExecutionHandler((r, executor) -> {
                // .....
            });
            // 使用预设的拒绝策略
            threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    
            return threadPoolTaskExecutor;
        }
    
    
    
    
        public static void main(String[] args) {
            SpringApplication.run(Application.class, args);
        }
    }

    2. 配置线程池

    Spring异步线程池的接口类,其实质是java.util.concurrent.Executor。

    Spring 已经实现的异常线程池:
    1. SimpleAsyncTaskExecutor:
    不是真的线程池,这个类不重用线程,每次调用都会创建一个新的线程。
    2. SyncTaskExecutor:
    这个类没有实现异步调用,只是一个同步操作。只适用于不需要多线程的地方
    3. ConcurrentTaskExecutor:
    Executor的适配类,不推荐使用。如果ThreadPoolTaskExecutor不满足要求时,才用考虑使用这个类
    4. SimpleThreadPoolTaskExecutor:
    是Quartz的SimpleThreadPool的类。线程池同时被quartz和非quartz使用,才需要使用此类
    5. ThreadPoolTaskExecutor:
    最常使用,推荐。其实质是对java.util.concurrent.ThreadPoolExecutor的包装。

    3. 添加@Async注解

        /**
         * 异步调用返回Future
         * 
         * @param i
         * @return
         */
        @Async
        public Future<String> asyncInvokeReturnFuture(int i) {
            log.info("asyncInvokeReturnFuture, parementer={}", i);
            Future<String> future;
            try {
                Thread.sleep(1000 * 1);
                future = new AsyncResult<String>("success:" + i);
            } catch (InterruptedException e) {
                future = new AsyncResult<String>("error");
            }
            return future;
        }

    4. 通过XML文件配置

        <!-- 等价于 @EnableAsync, executor指定线程池 -->
        <task:annotation-driven executor="xmlExecutor"/>
        <!-- id指定线程池产生线程名称的前缀 -->
        <task:executor
            id="xmlExecutor"
            pool-size="5-25"
            queue-capacity="100"
            keep-alive="120"
            rejection-policy="CALLER_RUNS"/>

    5. 异常处理

    在调用方法时,可能出现方法中抛出异常的情况。在异步中主要有有两种异常处理方法:
    1. 对于方法返回值是Futrue的异步方法:
    a) 一种是在调用future的get时捕获异常;
    b) 在异常方法中直接捕获异常
    2. 对于返回值是void的异步方法:
    通过AsyncUncaughtExceptionHandler处理异常

    /**
     * 通过实现AsyncConfigurer自定义线程池,包含异常处理
     */
    @Service
    public class MyAsyncConfigurer implements AsyncConfigurer{
        private static final Logger log = LoggerFactory.getLogger(MyAsyncConfigurer.class);
    
        @Override
        public Executor getAsyncExecutor() {
            ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();  
            threadPool.setCorePoolSize(1);  
            threadPool.setMaxPoolSize(1);  
            threadPool.setWaitForTasksToCompleteOnShutdown(true);  
            threadPool.setAwaitTerminationSeconds(60 * 15);  
            threadPool.setThreadNamePrefix("MyAsync-");
            threadPool.initialize();
            return threadPool;  
        }
    
        @Override
        public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
             return new MyAsyncExceptionHandler();  
        }
    
        /**
         * 自定义异常处理类
         */
        class MyAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {  
    
            @Override  
            public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {  
                log.info("Exception message - " + throwable.getMessage());  
                log.info("Method name - " + method.getName());  
                for (Object param : obj) {  
                    log.info("Parameter value - " + param);  
                }  
            }  
    
        } 
    
    }

    6. 参考文章

    [1] Spring Boot系列二 Spring @Async异步线程池用法总结

    [2] Spring Boot开启异步任务 子线程

  • 相关阅读:
    excel 常用小技巧
    如何以正确的顺序重新安装驱动程序
    kaby LAKE 仅支持 Windows10
    关闭远程计算机CMD命令
    根据IP查主机名
    Charles安装与使用
    常用的算法思想总结
    iOS学习之单例模式
    PHP之简单实现MVC框架
    Objective-C 继承和多态
  • 原文地址:https://www.cnblogs.com/jpfss/p/10273219.html
Copyright © 2011-2022 走看看