Spring 异步任务的创建、自定义配置和原理

栏目: Java · 发布时间: 5年前

内容简介:当我们调用默认情况下,Spring将搜索关联的线程池定义:上下文中的唯一

@EnableAsync@Configuration 类一起使用,如下所示,为整个Spring应用程序上下文启用注释驱动的异步处理

@Configuration
 @EnableAsync
 public class AppConfig {

 }
复制代码

2.2 编写异步任务

@Component
public class EmailService {
    @Async
    //无返回类型
    public void send(String from, String to, String subject, String text) {
        //do send
    }
    
    @Async
    //有返回类型
    public Future<String> send(String from, String to, String subject, String text) {
        System.out.println("Execute method asynchronously - "
         + Thread.currentThread().getName());
        try {
           Thread.sleep(5000);
           return new AsyncResult<String>("hello world !!!!");
        } catch (InterruptedException e) {
           //
        }
    
        return null;
    }
}
复制代码

当我们调用 send() 方法时,这个任务就会异步去执行, @Async 不仅可以用在方法上,还可以用在Bean类上,如果在类所有方法都是异步的

3 自定义Executor

默认情况下,Spring将搜索关联的线程池定义:上下文中的唯一 TaskExecutor bean ,或者另一个名为“taskExecutor”的 Executor bean 。如果两者都不可解析,则将使用 SimpleAsyncTaskExecutor 处理异步方法调用。此外,具有 void 返回类型的带注解的方法不能将任何异常发送回调用者。默认情况下,仅记录下此类未捕获的异常。

要自定义所有这些,需要实现 AsyncConfigurer 并提供:

  • 自定义 Executor : 通过 getAsyncExecutor() 方法实现
  • 自定义 AsyncUncaughtExceptionHandler : 通过 getAsyncUncaughtExceptionHandler() 来实现

注意: AsyncConfigurer 配置类在应用程序上下文引导程序的早期初始化。如果你对其他 bean 有任何依赖,请确保尽可能地声明它们为 Lazy ,以便让它们通过其他后处理器。

@Configuration
@EnableAsync
public class AppConfig implements AsyncConfigurer {

     @Override
     public Executor getAsyncExecutor() {
         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
         executor.setCorePoolSize(7);
         executor.setMaxPoolSize(42);
         executor.setQueueCapacity(11);
         executor.setThreadNamePrefix("MyExecutor-");
         executor.setWaitForTasksToCompleteOnShutdown(true);//默认是false,即shutdown时会立即停止并终止当前正在执行任务
         executor.setRejectedExecutionHandler((r, executor1) -> {
            for(;;) {
                try {
                    executor1.getQueue().put(r);
                } catch (InterruptedException e) {
                    e.printStackTrace();

                }
                return;
            }
        });//指定被拒绝任务的处理方法,经过测试当并发量超过队列长度时可以继续执行,否则会抛出 org.springframework.core.task.TaskRejectedException异常
         executor.initialize();
         return executor;
     }
    
     @Override
     public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
         return new CustomAsyncExceptionHandler();//自定义未捕获异常处理,参考 4 异常处理 小节
     }
}
复制代码

3.1 在方法级别自定义Executor

以上为应用级别重写Executor,Spring还提供方法级别重写: 开启Async并自定义Executor:

@Configuration
@EnableAsync
public class SpringAsyncConfig {
    
   @Bean(name = "threadPoolTaskExecutor")
   public Executor threadPoolTaskExecutor() {
       return new ThreadPoolTaskExecutor();
   }
}
复制代码

使用自定义Executor

@Async("threadPoolTaskExecutor")
public void asyncMethodWithConfiguredExecutor() {
    System.out.println("Execute method with configured executor - "
      + Thread.currentThread().getName());
}
复制代码

4 异常处理

当方法返回类型是 Future 时,异常处理很容易 - Future.get()方法将抛出异常。

但是,如果返回类型为void,则异常不会传播到调用线程。因此,我们需要添加额外的配置来处理异常。

我们将通过实现 AsyncUncaughtExceptionHandler 接口来创建自定义异步异常处理程序。当存在任何未捕获的异步异常时,将调用 handleUncaughtException() 方法:

public class CustomAsyncExceptionHandler
  implements AsyncUncaughtExceptionHandler {
 
    @Override
    public void handleUncaughtException(
      Throwable throwable, Method method, Object... obj) {
  
        System.out.println("Exception message - " + throwable.getMessage());
        System.out.println("Method name - " + method.getName());
        for (Object param : obj) {
            System.out.println("Parameter value - " + param);
        }
    }
     
}
复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Docker从入门到实战

Docker从入门到实战

黄靖钧 / 机械工业出版社 / 2017-6 / 69.00元

本书从Docker的相关概念与基础知识讲起,结合实际应用,通过不同开发环境的实战例子,详细介绍了Docker的基础知识与进阶实战的相关内容,以引领读者快速入门并提高。 本书共19章,分3篇。第1篇容器技术与Docker概念,涵盖的内容有容器技术、Docker简介、安装Docker等。第2篇Docker基础知识,涵盖的内容有Docker基础、Docker镜像、Dockerfile文件、Dock......一起来看看 《Docker从入门到实战》 这本书的介绍吧!

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器