目录
前言
线程池是为突然大量爆发的线程设计的,通过有限的几个固定线程为大量的操作服务,减少了创建和销毁线程所需的时间,从而提高效率。如果一个线程的时间非常长,就没必要用线程池了(不是不能作长时间操作,而是不宜。),况且还不能控制线程池中线程的开始、挂起、和中止。
说明
- 1.配置解释
当一个任务通过execute(Runnable)方法欲添加到线程池时:
1.1、 如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
1.2 如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
1.3、如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。
1.4、 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。
也就是:处理任务的优先级为:核心线程corePoolSize、任务队列workQueue、最大线程 maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
1.5、 当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。
allowCoreThreadTimeout:允许核心线程超时
rejectedExecutionHandler:任务拒绝处理器
两种情况会拒绝处理任务:
当线程数已经达到maxPoolSize,切队列已满,会拒绝新任务
当线程池被调用shutdown()后,会等待线程池里的任务执行完毕,再shutdown。如果在调用shutdown()和线程池真正shutdown之间提交任务,会拒绝新任务
线程池会调用rejectedExecutionHandler来处理这个任务。如果没有设置默认是AbortPolicy,会抛出异常
ThreadPoolExecutor类有几个内部实现类来处理这类情况:
AbortPolicy 丢弃任务,抛运行时异常
CallerRunsPolicy 执行任务
DiscardPolicy 忽视,什么都不会发生
DiscardOldestPolicy 从队列中踢出最先进入队列(最后一个执行)的任务
实现RejectedExecutionHandler接口,可自定义处理器
代码实现
配置类
package *********;
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.concurrent.ThreadPoolTaskExecutor;
import java.lang.reflect.Method;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author
* @Title: AsyncConfig
* @Description:
* @Copyright:
* @Company:
* @Date 2020-03-19-9:31
*/
@Configuration
public class AsyncConfig implements AsyncConfigurer {
private int corePoolSize = 5;//核心线程数
private int maxPoolSize = 20;//最大线程数
private int keepAliveSeconds = 60 * 10;//线程空闲时间
private String threadNamePrefix = "my-Thread";//线程对象的名字前缀
private int queueCapacity = 5;
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
//设置核心线程数
taskExecutor.setCorePoolSize(corePoolSize);
//设置最大线程数
taskExecutor.setMaxPoolSize(maxPoolSize);
//设置线程空闲时间
taskExecutor.setKeepAliveSeconds(keepAliveSeconds);
//设置线程对象的名字前缀
taskExecutor.setThreadNamePrefix(threadNamePrefix);
//设置缓存队列的容量
taskExecutor.setQueueCapacity(queueCapacity);
//设置拒绝处理的策略(当线程池无法处理新的任务时,该执行什么策略)
//new ThreadPoolExecutor.CallerRunsPolicy() 该策略为选择调用者线程进行处理
//new ThreadPoolExecutor.AbortPolicy() 该策略为丢弃任务并抛出RejectedExecutionException异常(不设置时默认此策略)
//new ThreadPoolExecutor.DiscardPolicy() 该策略为丢弃任务,但是不抛异常
//new ThreadPoolExecutor.DiscardOldestPolicy() 该策略为丢弃队列最前面的任务,然后重新尝试执行任务
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//初始化线程池
taskExecutor.initialize();
return taskExecutor;
}
//异常任务执行过程中的错误处理
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncUncaughtExceptionHandler() {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
//自定义处理
}
};
}
}
@Configuration
class AsyncConfig1 {
private int corePoolSize = 5;//核心线程数
private int maxPoolSize = 20;//最大线程数
private int keepAliveSeconds = 60 * 10;//线程空闲时间
private String threadNamePrefix = "my-Thread";//线程对象的名字前缀
private int queueCapacity = 5;
@Bean
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
//设置核心线程数
taskExecutor.setCorePoolSize(corePoolSize);
//设置最大线程数
taskExecutor.setMaxPoolSize(maxPoolSize);
//设置线程空闲时间
taskExecutor.setKeepAliveSeconds(keepAliveSeconds);
//设置线程对象的名字前缀
//taskExecutor.setThreadNamePrefix(threadNamePrefix);
//设置缓存队列的容量
taskExecutor.setQueueCapacity(queueCapacity);
//允许核心线程超时
taskExecutor.setAllowCoreThreadTimeOut(true);
//设置拒绝处理的策略(当线程池无法处理新的任务时,该执行什么策略)
//new ThreadPoolExecutor.CallerRunsPolicy() 该策略为选择调用者线程进行处理
//new ThreadPoolExecutor.AbortPolicy() 该策略为丢弃任务并抛出RejectedExecutionException异常(不设置时默认此策略)
//new ThreadPoolExecutor.DiscardPolicy() 该策略为丢弃任务,但是不抛异常
//new ThreadPoolExecutor.DiscardOldestPolicy() 该策略为丢弃队列最前面的任务,然后重新尝试执行任务
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
taskExecutor.setThreadFactory(new ThreadFactory() {
private final AtomicLong index = new AtomicLong(1);
@Override
public Thread newThread(Runnable r) {
return new Thread(r, "thread-" + index.getAndIncrement());
}
});
//初始化线程池
//taskExecutor.initialize();当标记为Bean时,不需要调用此方法初始化,spring会自动调用此方法进行初始化
return taskExecutor;
}
//异常任务执行过程中的错误处理
@Bean
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new AsyncUncaughtExceptionHandler() {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
//自定义处理
}
};
}
}
当需要执行异步调用时使用@Async注解
@Async
public void AsyncExecutor(Object... objects){
//执行任务
}
当需要执行有返回的任务时,返回值定义为Future<T>
@Async
public Future<String> AsyncExecutor(Object... objects){
//执行任务
return new AsyncResult<String>(JSON.toJSONString(objects));
}