1.应用场景
为了使线程池的使用更加的规范,同时合理的规划线程的数量,避免资源消耗。
2.代码理解
下面是ThreadPoolExecutor的构造函数。
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
参数的含义介绍
参数 | 含义 |
---|---|
corePoolSize | 指定了线程池中的线程数量,它的数量决定了添加的任务是开辟新的线程去执行,还是放到workQueue任务队列中去 |
maximumPoolSize | 指定了线程池中的最大线程数量 |
keepAliveTime | 当线程池中空闲线程数量超过corePoolSize时,多余的线程会在多长时间内被销毁 |
unit | keepAliveTime的单位 |
workQueue | 任务队列,被添加到线程池中,但尚未被执行的任务 |
threadFactory | 线程工厂,用于创建线程 |
handler | 拒绝策略;当任务超出线程池数量时,如何拒绝任务 |
2.1 workQueue队列
队列 | 类名 | 介绍 |
---|---|---|
直接提交队列 | SynchronousQueue | 没有容量,执行一个插入就会阻塞,删除就会唤醒,此时,如果有多条线程任务进来,会直接启用maximumPoolSize对应的线程数量,超出的直接执行拒绝策略 |
有界的任务队列 | ArrayBlockingQueue | 若有新的任务加入线程,线程池会创建新的线程,直到创建的线程达到corePoolSize,再有线程进来,会存在队列当中,如果队列存满,会继续创建线程直到达到maximumPoolSize之后执行拒绝策略 |
无界的任务队列 | LinkedBlockingQueue | 线程池的任务队列可以无限制的添加新的任务,而线程池能够创建的最大的线程数量就是corePoolSize,maximumPoolSize这个参数等于已经无效了 |
优先任务队列 | PriorityBlockingQueue | 在任务中设置优先级,队列会根据优先级进行任务的重排,执行优先级高的任务,任务的执行数量不会超过corePoolSize |
2.2 拒绝策略
我们这里只探讨有界队列的情况,因为只有有界队列才可能出现超出队列且超出最大线程数量的情况。
策略 | 含义 |
---|---|
AbortPolicy策略 | 该策略会直接抛出异常,阻止系统正常工作 |
CallerRunsPolicy策略 | 如果线程池的线程数量达到上限,该策略会把任务队列中的任务放在调用者线程当中运行 |
DiscardOledestPolicy策略 | 该策略会丢弃任务队列中最老的一个任务,也就是当前任务队列中最先被添加进去的,马上要被执行的那个任务,并尝试再次提交 |
DiscardPolicy策略 | 该策略会默默丢弃无法处理的任务,不予任何处理。当然使用此策略,业务场景中需允许任务的丢失 |
2.3 自定义线程工厂
public void executeExecutor(){
new ThreadPoolExecutor(1, 2, 1000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r,r.hashCode() + "");
return thread;
}
},new ThreadPoolExecutor.CallerRunsPolicy());
}
2.4 自定义拒绝策略
new ThreadPoolExecutor(1, 2, 1000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(10),Executors.defaultThreadFactory(), new RejectedExecutionHandler() {
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println(r.toString()+"执行了拒绝策略");
}
});
3.SpringBoot下使用线程池
spring-context包下有一个ThreadPoolTaskExcecutor
@Configuration
public class ThreadPoolConfig
{
// 核心线程池大小
private int corePoolSize = 10;
// 最大可创建的线程数
private int maxPoolSize = 20;
// 队列最大长度
private int queueCapacity = 1000;
// 线程池维护线程所允许的空闲时间
private int keepAliveSeconds = 300;
@Bean(name = "threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor()
{
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(maxPoolSize);
executor.setCorePoolSize(corePoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveSeconds);
// 线程池对拒绝任务(无线程可用)的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
}
使用
@Service
public TestServiceImpl implements TestService{
@Autowird
private ThreadPoolTaskExecutor threadPoolTaskExecutor;
public void test(){
threadPoolTaskExecutor.execute(new Task())
}
}
还有一个线程池类可能也会用到,就是执行定时任务的线程池ScheduledThreadPoolExecutor
,SpringBoot中注入Bean如下
@Configuration
public class ThreadPoolConfig
{
// 核心线程池大小
private int corePoolSize = 50;
/**
* 执行周期性或定时任务
*/
@Bean(name = "scheduledExecutorService")
protected ScheduledExecutorService scheduledExecutorService()
{
return new ScheduledThreadPoolExecutor(corePoolSize,
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build())
{
@Override
protected void afterExecute(Runnable r, Throwable t)
{
super.afterExecute(r, t);
Threads.printException(r, t);
}
};
}
}
用法如下
@Service
public TestServiceImpl implements TestService{
@Autowird
private ScheduledExecutorService scheduledExecutorService;
public void test(){
scheduledExecutorService.scheduleAtFixedRate(new Task(),0,30,TimeUnit.Seconds);
// 0表示首次执行任务的延迟时间
//30表示执行任务的时间间隔
//TimeUnit.Seconds表示时间的单位
}
}