五种线程池
Java通过Executors提供五种线程池,分别为:
1、newSingleThreadExecutor
创建使用在无界队列上操作的单个工作线程的执行器。(但是请注意,如果这个单线程在关闭之前的执行过程中由于失败而终止,如果需要执行后续任务,将会有一个新的线程取代它。)任务保证按顺序执行,并且在任何给定时间活动的任务不超过一个。与newFixedThreadPool(1)不同,返回的执行器保证不会被重新配置以使用其他线程。 返回: 新创建的单线程执行器
2、newFixedThreadPool
创建一个线程池,该线程池重用在共享无界队列上操作的固定数量的线程,并在需要时使用提供的ThreadFactory创建新线程。在任何时候,最多有nThreads线程处于活动状态,正在处理任务。如果在所有线程都处于活动状态时提交额外的任务,它们将在队列中等待,直到一个线程可用。如果任何线程在关闭之前的执行过程中由于失败而终止,如果需要执行后续任务,则会有一个新线程取代它的位置。在显式关闭池之前,池中的线程将一直存在。 参数: nThreads——池中的线程数 创建新线程时使用的工厂 返回: 新创建的线程池 抛出: NullPointerException -如果threadFactory是空的 IllegalArgumentException -如果nThreads <= 0
3、newScheduledThreadPool
创建一个线程池,该线程池可以调度命令在给定延迟后运行或定期执行。 参数: corePoolSize—要保留在池中的线程数,即使它们是空闲的 threadFactory——执行器创建新线程时使用的工厂 返回: 新创建的调度线程池 抛出: IllegalArgumentException -如果corePoolSize < 0 NullPointerException -如果threadFactory是空的
4、newCachedThreadPool
创建一个线程池,该线程池根据需要创建新线程,但在以前构造的线程可用时重用它们。这些池通常会提高执行许多短期异步任务的程序的性能。执行调用将重用先前构造的线程(如果可用)。如果没有可用的现有线程,将创建一个新线程并将其添加到池中。60秒内未使用的线程将被终止并从缓存中删除。因此,长时间保持空闲状态的池不会消耗任何资源。请注意,可以使用ThreadPoolExecutor构造函数创建具有相似属性但不同细节(例如,超时参数)的池。 返回: 新创建的线程池
5、newWorkStealingPool
创建一个线程池,该线程池维护足够的线程以支持给定的并行级别,并且可以使用多个队列来减少争用。并行性级别对应于积极参与或可用参与任务处理的最大线程数。实际的线程数可以动态地增加和减少。工作窃取池不能保证所提交任务的执行顺序。 参数: 并行度——目标并行度级别 返回: 新创建的线程池 抛出: IllegalArgumentException -如果并行度<= 0 自: JDK1.8
ThreadPoolExecutor类讲解
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
threadFactory, defaultHandler);
}
1、参数讲解
maximumPoolSize:最大线程数
keepAlivedTime:线程存活时间
unit:线程存活时间单位
workQueue:阻塞队列,用来存放待处理的任务
threadFactory:线程工厂,用来创建线程池中的工作线程
handler:拒绝策略,当线程池处于满负荷状态时,无法处理后续进来的任务,便会采用拒绝策略。\
四种拒绝策略讲解
1、AbortPolicy:默认使用策略,丢弃该任务总是抛出RejectedExecutionException
/**
* A handler for rejected tasks that throws a
* {@link RejectedExecutionException}.
*
* This is the default handler for {@link ThreadPoolExecutor} and
* {@link ScheduledThreadPoolExecutor}.
*/
public static class AbortPolicy implements RejectedExecutionHandler {
/**
* Creates an {@code AbortPolicy}.
*/
public AbortPolicy() { }
/**
* Always throws RejectedExecutionException.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
* @throws RejectedExecutionException always
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
2、CallerRunsPolicy:只要线程池没有被shutdown(),提交任务的线程通过执行r.run()方法直接以普通的方法执行
/**
* A handler for rejected tasks that runs the rejected task
* directly in the calling thread of the {@code execute} method,
* unless the executor has been shut down, in which case the task
* is discarded.
*/
public static class CallerRunsPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code CallerRunsPolicy}.
*/
public CallerRunsPolicy() { }
/**
* Executes task r in the caller's thread, unless the executor
* has been shut down, in which case the task is discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}
3、DisCardPlicy:直接丢弃,不做任务处理
/**
* A handler for rejected tasks that silently discards the
* rejected task.
*/
public static class DiscardPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardPolicy}.
*/
public DiscardPolicy() { }
/**
* Does nothing, which has the effect of discarding task r.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
4,DisCardOldestPolicy::只要线程池没有被shutdown(),则通过e.getQueue().poll()把队列头部等待最久 的任务丢弃,然后把当前任务通过execute()方法提交到阻塞队列
/**
* A handler for rejected tasks that discards the oldest unhandled
* request and then retries {@code execute}, unless the executor
* is shut down, in which case the task is discarded. This policy is
* rarely useful in cases where other threads may be waiting for
* tasks to terminate, or failures must be recorded. Instead consider
* using a handler of the form:
* <pre> {@code
* new RejectedExecutionHandler() {
* public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
* Runnable dropped = e.getQueue().poll();
* if (dropped instanceof Future<?>) {
* ((Future<?>)dropped).cancel(false);
* // also consider logging the failure
* }
* e.execute(r); // retry
* }}}</pre>
*/
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardOldestPolicy} for the given executor.
*/
public DiscardOldestPolicy() { }
/**
* Obtains and ignores the next task that the executor
* would otherwise execute, if one is immediately available,
* and then retries execution of task r, unless the executor
* is shut down, in which case task r is instead discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
}