有注解和xml两种方式,我这里只大概记录一下注解方式,趋势=-=
首先新建一个配置类,必须被spring管理,这里就不多说了…
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import java.lang.reflect.Method;
import java.util.concurrent.*;
/**
* Created by rdd on 2019/2/11.
*/
@Configuration//配置类
@Slf4j//日志
@EnableAsync//开启注解
//可以继承或者实现
//public class AsyncServiceConfig extends AsyncConfigurerSupport {
public class AsyncServiceConfig implements AsyncConfigurer {
/**
* 可以建多个线程池,然后使用@Async(value = "asyOneExecutor")可以指定不同线程池
* 根据不同线程池的主要使用方式去选择对应的线程池
* 不指定则使用getAsyncExecutor方法返回的线程池
* @return
*/
@Bean
public ThreadPoolTaskScheduler asyOneExecutor() {
ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
scheduler.setPoolSize(20);
scheduler.setThreadNamePrefix("asy1-");
scheduler.setAwaitTerminationSeconds(60);
scheduler.setWaitForTasksToCompleteOnShutdown(true);
return scheduler;
}
@Bean
public ThreadPoolExecutor asyTwoExecutor() {
//创建一个简单的线程池
// ExecutorService executorService = Executors.newSingleThreadExecutor();
//自定义个数线程池
ThreadFactory threadFactory = new ThreadFactoryBuilder().setDaemon(true).build();
ThreadPoolExecutor pool = new ThreadPoolExecutor(3, 5, 50, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory);
return pool;
}
@Override
public Executor getAsyncExecutor() {
Executor executor = this.asyOneExecutor();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
//异常捕捉
return new AsyncServiceConfig.SpringAsyncExceptionHandler();
}
class SpringAsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... obj) {
// 错误日志
log.error("Exception occurs in async method", throwable.getMessage());
}
}
}
执行效果.
执行就可以看到异步方法使用的线程池了,不指定不写也可以,spring会给一个默认的简单异步线程池;
注意:
实现AsyncConfigurer接口只能实现一个类,否则会报错如下(很明显了):
Injection of autowired dependencies failed; nested exception is java.lang.IllegalStateException: Only one AsyncConfigurer may exist
我们甚至可以不实现AsyncConfigurer,我们可以在Spring环境中配置多个Executor类型的Bean,在使用@Async注解时,将注解的value指定为你Executor类型的BeanName,这样也可以就是不方便管理而已…
最后需要在需要异步的方法或者类上加上注解@Async就可以愉快的使用异步了…
当然异步执行还有很多东西,比如执行完成后返回参数,计数等等,这些在这篇就不写出来了,有空再整理.