茂展的分享博客

线程池

线程池

ThreadPoolExecutor类

JDK 1.5以后,Java提供一个线程池ThreadPoolExecutor类

1
2
3
4
5
6
7
//corePoolSize 线程池维护线程的最少数量
//maximumPoolSize 线程池维护线程的最多数量
// keepAliveTime 线程池维护线程所允许的空闲时间
// workQueue 任务队列 用来存放我们所定义的任务处理线程
// threadFactory 线程创建厂
// handler 线程池对拒绝任务的处理策略
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler);

ThreadPoolExecutor根据coolPoolSize和maximumPoolSize设置的边界自动调整池大小,当有新的任务进来的时候,判断当前线程池中的线程数是否小于corePoolSize,如果小于,就创建新的线程。然后如果大于corePoolSize并小于maximumPoolSize并队列的没有满,则放进队列中,如果队列满的时候,就创建新的线程来处理请求。

线程池中任务有三种排队策略

1.直接提交

直接提交表示线程池不对任务进行缓存。新任务直接交给线程池,当线程池没有新的线程处理任务的时候,创建一个新的线程处理此任务。这种策略需要线程池具有无限增长的可能性。实现:SynchronousQueue

2.无界队列

使用无界队列,例如linkedBlockingQueue,将导致在所有的corePoolSize线程都在忙的时候,新任务会在队列中等待,这样创建的线程不会超过corePoolSize,因此maximumPoolSize是无效的。当每个任务完全独立于其他任务,即任务互不影响时,适合使用无界队列;例如在web服务器中,这种排队可用于处理瞬间突发请求,当请求已超过队列所能处理的平均数到达时,此策略允许无界线程具有增长的可能性。

3.有界队列

初始的poolSize < corePoolSize,提交的runnable任务,会直接做为new一个Thread的参数,立马执行 。当提交的任务数超过了corePoolSize,会将当前的runable提交到一个block queue中。有界队列满了之后,如果poolSize < maximumPoolsize时,会尝试new 一个Thread的进行救急处理,立马执行对应的runnable任务。如果仍然也无法处理,就执行reject操作。例如:ArrayBlockingQueue

线程池中有四种拒绝策略

1.AbortPolicy

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {throw new RejectedExecutionException();}

处理程序遭到拒绝将抛出运行时RejectedExecutionException,这种策略直接抛出异常,丢弃任务。(jdk默认策略,队列满并线程满时直接拒绝添加新任务,并抛出异常)

2.DiscardPolicy

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {}

这种策略和AbortPolicy几乎一样,也是丢弃任务,只不过他不抛出异常,不能执行的任务将被删除

3.DiscardOldestPolicy

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) {e.getQueue().poll();e.execute(r); }}

如果执行程序尚未关闭,则位于工作队列头部的任务将被删除,然后重试执行程序(如果再次失败,则重复此过程)

4.CallerRunsPolicy

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { if (!e.isShutdown()) { r.run(); }}

重试添加当前的任务,它会自动重复调用execute()方法,很有可能造成当前线程也被阻塞

------本文结束感谢阅读------
🐶 您的支持将鼓励我继续创作 🐶