Spring реализует асинхронную обработку задач

Spring

1. Spring реализует асинхронные задачи

Spring предоставляет интерфейсorg.springframework.core.task.TaskExecutor, этот интерфейс реализуетjava.util.concurrent.ExecutorИнтерфейс, интерфейс Executor, студенты, знакомые с многопоточностью, должны знать, это интерфейс верхнего уровня пула потоков java, что означает, что TaskExecutor также является пулом потоков и выполняет наши асинхронные задачи через пул потоков.

1. На основе конфигурации xml

Пул потоков TaskExecutor настраивается через XML-файл. Конкретная конфигурация выглядит следующим образом.

<!--
        代码中引用即可 @Autowired
        id:线程池名称,池中线程的名称前缀 ThreadPoolTaskExecutor
        pool-size:单一的值表示核心线程数量,如果是5-25,表示core-max
        queue-capacity:队列容量,默认是无界队列,可能会导致OOM,而且在无界队列的情况下,最大线程就无效了,只有固定线程才适合无界队列
        rejection-policy:当都满了的时候的拒绝策略,AbortPolice,CallerRunsPolicy,DiscardPolicy,DiscardOldestPolicy
        keep-alive:超过核心线程数量的线程的保活时间,如果设置为0,表示任务执行完之后立即回收 单位:s
        -->
<task:executor id="myExecutor" 
               pool-size="5-25" 
               queue-capacity="200" 
               rejection-policy="ABORT" 
               keep-alive="120"/>

Из приведенной выше конфигурации видно, что на самом деле это обычная конфигурация пула потоков.

Как использовать:

public class MyAsync {

    /**
     * 注入线程池
     */
    @Autowired
    private TaskExecutor taskExecutor;

    /**
     * 无返回值、无参数
     */
    public void async() {
       // taskExecutor.execute(new MyTask());
    }

    /**
     * 有参数、无返回值
     *
     * @param param
     */
    public void param(String param) {
        // taskExecutor.execute(new MyTask());
    }

    /**
     * Future 异步返回
     *
     * @return
     */
    public Future<String> future() {
        // taskExecutor.execute(new MyTask());
        return new AsyncResult<String>("result");
    }

    /**
     * CompletableFuture 异步返回
     *
     * @return
     */
    public CompletableFuture<String> completedFuture() {
        // taskExecutor.execute(new MyTask());
        return CompletableFuture.completedFuture("result");
    }
}

На основе конфигурации xml его также можно настроить для включения@AsyncОбратите внимание, что конкретная конфигурация выглядит следующим образом:

<!--
        该标签是用于开启注解模式的,识别@Scheduled
        executor:executor bean name
        scheduler:scheduler bean name
        exception-handler:ThreadPoolTaskExecutor exception handler bean name
        mode:代理方式 1.AspectJ 2.JDK Proxy  默认JDK Proxy
        proxy-target-class:是否代理目标类 默认false
        -->
    <task:annotation-driven executor="myExecutor"/>

Использовать напрямую@AsyncАннотацию можно использовать следующим образом:

public class MyAsync {

    /**
     * 无返回值、无参数
     */
    @Async
    public void async() {
        
    }

    /**
     * 有参数、无返回值
     *
     * @param param
     */
    @Async
    public void param(String param) {

    }

    /**
     * Future 异步返回
     *
     * @return
     */
    @Async
    public Future<String> future() {

        return new AsyncResult<String>("result");
    }

    /**
     * CompletableFuture 异步返回
     *
     * @return
     */
    @Async
    public CompletableFuture<String> completedFuture() {

        return CompletableFuture.completedFuture("result");
    }
}

2. На основе конфигурации Java

Конфигурация на основе конфигурации Java должна быть реализованаorg.springframework.scheduling.annotation.AsyncConfigurerИнтерфейс, конкретный код выглядит следующим образом.

@Configuration
public class MyAsyncConfigure implements AsyncConfigurer {


    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.execute(myTask());
        Future<?> future = executor.submit(myTask());
        return executor;
    }

    /**
     * 异常处理
     *
     * @return
     */
    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return null;
    }

    public MyTask myTask() {
        return new MyTask();
    }
}

3. Аннотация на основе

Конфигурация на основе аннотаций выполняется с помощью@EnableAsyncа также@Asycдве аннотации

@Configuration
@EnableAsync //开启异步,相当于TaskExecutor
public class MyConfiguration {
    /**
     * 配置线程池
     * 如果不配置,@EnableAsync默认core-size=1
     *
     * @return
     */
    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor scheduler = new ThreadPoolTaskExecutor();
        scheduler.setCorePoolSize(10);
        return scheduler;
    }
}

Как использовать:

public class MyAsync {

    /**
     * 无返回值、无参数
     */
    @Async
    public void async() {
    }

    /**
     * 有参数、无返回值
     *
     * @param param
     */
    @Async
    public void param(String param) {

    }

    /**
     * Future 异步返回
     *
     * @return
     */
    @Async
    public Future<String> future() {
        return new AsyncResult<String>("result");
    }

    /**
     * CompletableFuture 异步返回
     *
     * @return
     */
    @Async
    public CompletableFuture<String> completedFuture() {
        return CompletableFuture.completedFuture("result");
    }
}

4. Обработка исключений

1.xml и аннотации

Если вы используете конфигурацию xml или конфигурацию аннотаций, необходимо реализовать обработку исключений.org.springframework.aop.interceptor.AsyncUncaughtExceptionHandlerинтерфейс, который имеет простую реализациюorg.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler, эта реализация записывает журнал исключений, мы также можем реализовать этот интерфейс для настройки обработки исключений.

public class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
    @Override
    public void handleUncaughtException(Throwable ex, Method method, Object... params) {

    }
}

xml использовать:

<!--异常处理-->
<bean id="myAsyncUncaughtExceptionHandler"      class="com.ly.task.async.MyAsyncUncaughtExceptionHandler"/>

<task:annotation-driven executor="myExecutor"
                            exception-handler="myAsyncUncaughtExceptionHandler"/>

Пока метод аннотации настроен, он будет автоматически вызываться при возникновении исключения.

2.java config

В конфигурации java-конфига выше мы реализовалиorg.springframework.scheduling.annotation.AsyncConfigurerинтерфейс для настройки, этот интерфейс имеетorg.springframework.scheduling.annotation.AsyncConfigurer#getAsyncUncaughtExceptionHandlerметод, вы можете напрямую обрабатывать исключения в этом методе.