Spring异步线程池

在Spring中存在一个AsyncConfigurer接口,它是一个可以配置异步线程池的接口,实现源码如下:

package org.springframework.scheduling.annotation;

import java.util.concurrent.Executor;

import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.lang.Nullable;

public interface AsyncConfigurer {

	/**
	 * The {@link Executor} instance to be used when processing async
	 * method invocations.
	 */
	@Nullable
	default Executor getAsyncExecutor() {
		return null;
	}

	/**
	 * The {@link AsyncUncaughtExceptionHandler} instance to be used
	 * when an exception is thrown during an asynchronous method execution
	 * with {@code void} return type.
	 */
	@Nullable
	default AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
		return null;
	}

}

代码比较简单,其中getAsyncExecutor方法返回的是一个自定义线程池,这样在开启异步时,线程池就会提供空闲线程来执行异步任务。因为线程中的业务逻辑可能抛出异常,所以还有一个处理异常的处理器方法。为了使得异步可用,Spring还提供了注解@EnableAsync,如果Java配置文件标注它,那么Spring就会开启异步可用,这样就可以使用注解@Async驱动Spring使用异步调用。下面我们看一下异步实例的实现代码:

package com.martin.config.other.async;

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

/**
 * @author: martin
 * @date: 2020/2/5
 */
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer {
    //定义线程池
    @Override
    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor poolExecutor = new ThreadPoolTaskExecutor();
        //核心线程数
        poolExecutor.setCorePoolSize(10);
        //线程池最大线程数
        poolExecutor.setMaxPoolSize(30);
        //线程队列最大线程数
        poolExecutor.setQueueCapacity(2000);
        //初始化
        poolExecutor.initialize();
        return poolExecutor;
    }
}

代码中注解@EnableAsync表示开启Spring异步,并通过覆盖getAsyncExecutor方法,自定义一个线程池。这样就可以在业务代码中通过@Async注解使用该线程池执行异步操作。下面定义一个异步服务接口:

package com.martin.config.other.async;

/**
 * @author: martin
 * @date: 2020/2/5
 */
public interface AsyncService {
    void generateReport();
}



package com.martin.config.other.async;

import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

/**
 * @author: martin
 * @date: 2020/2/5
 */
@Service
@Slf4j
public class AsyncServiceImpl implements AsyncService {
    @Override
    @Async //声明使用异步调用
    public void generateReport() {
        log.error("报表生成线程名称:{}", Thread.currentThread().getName());
    }
}

这个方法比较简单,打印出了当前运行线程的名称,以便后续验证。需要注意的是这里使用了@Async注解,这样改方法在被调用的时候,它就会使用线程池的线程去执行它。启动服务后,日志打印如下:

报表生成线程名称:ThreadPoolTaskExecutor-3
报表生成线程名称:ThreadPoolTaskExecutor-4

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章