深入理解 Java 线程池 (3)

handler - 饱和策略。它是 RejectedExecutionHandler 类型的变量。当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务。线程池支持以下策略:

AbortPolicy - 丢弃任务并抛出异常。这也是默认策略。

DiscardPolicy - 丢弃任务,但不抛出异常。

DiscardOldestPolicy - 丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)。

CallerRunsPolicy - 只用调用者所在的线程来运行任务。

如果以上策略都不能满足需要,也可以通过实现 RejectedExecutionHandler 接口来定制处理策略。如记录日志或持久化不能处理的任务。

execute 方法

默认情况下,创建线程池之后,线程池中是没有线程的,需要提交任务之后才会创建线程。

提交任务可以使用 execute 方法,它是 ThreadPoolExecutor 的核心方法,通过这个方法可以向线程池提交一个任务,交由线程池去执行

execute 方法工作流程如下:

如果 workerCount < corePoolSize,则创建并启动一个线程来执行新提交的任务;

如果 workerCount >= corePoolSize,且线程池内的阻塞队列未满,则将任务添加到该阻塞队列中;

如果 workerCount >= corePoolSize && workerCount < maximumPoolSize,且线程池内的阻塞队列已满,则创建并启动一个线程来执行新提交的任务;

如果workerCount >= maximumPoolSize,并且线程池内的阻塞队列已满,则根据拒绝策略来处理该任务, 默认的处理方式是直接抛异常。

深入理解 Java 线程池

其他重要方法

在 ThreadPoolExecutor 类中还有一些重要的方法:

submit - 类似于 execute,但是针对的是有返回值的线程。submit 方法是在 ExecutorService 中声明的方法,在 AbstractExecutorService 就已经有了具体的实现。ThreadPoolExecutor 直接复用 AbstractExecutorService 的 submit 方法。

shutdown - 不会立即终止线程池,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务。

将线程池切换到 SHUTDOWN 状态;

并调用 interruptIdleWorkers 方法请求中断所有空闲的 worker;

最后调用 tryTerminate 尝试结束线程池。

shutdownNow - 立即终止线程池,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务。与 shutdown 方法类似,不同的地方在于:

设置状态为 STOP;

中断所有工作线程,无论是否是空闲的;

取出阻塞队列中没有被执行的任务并返回。

isShutdown - 调用了 shutdown 或 shutdownNow 方法后,isShutdown 方法就会返回 true。

isTerminaed - 当所有的任务都已关闭后,才表示线程池关闭成功,这时调用 isTerminaed 方法会返回 true。

setCorePoolSize - 设置核心线程数大小。

setMaximumPoolSize - 设置最大线程数大小。

getTaskCount - 线程池已经执行的和未执行的任务总数;

getCompletedTaskCount - 线程池已完成的任务数量,该值小于等于 taskCount;

getLargestPoolSize - 线程池曾经创建过的最大线程数量。通过这个数据可以知道线程池是否满过,也就是达到了 maximumPoolSize;

getPoolSize - 线程池当前的线程数量;

getActiveCount - 当前线程池中正在执行任务的线程数量。

使用示例 public class ThreadPoolExecutorDemo { public static void main(String[] args) { ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 500, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); for (int i = 0; i < 100; i++) { threadPoolExecutor.execute(new MyThread()); String info = String.format("线程池中线程数目:%s,队列中等待执行的任务数目:%s,已执行玩别的任务数目:%s", threadPoolExecutor.getPoolSize(), threadPoolExecutor.getQueue().size(), threadPoolExecutor.getCompletedTaskCount()); System.out.println(info); } threadPoolExecutor.shutdown(); } static class MyThread implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + " 执行"); } } } 四、Executors

JDK 的 Executors 类中提供了几种具有代表性的线程池,这些线程池 都是基于 ThreadPoolExecutor 的定制化实现

在实际使用线程池的场景中,我们往往不是直接使用 ThreadPoolExecutor ,而是使用 JDK 中提供的具有代表性的线程池实例。

newSingleThreadExecutor

创建一个单线程的线程池

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyysjg.html