模块 java.base

类 ThreadPoolExecutor

java.lang.Object
java.util.concurrent.AbstractExecutorService
java.util.concurrent.ThreadPoolExecutor
所有已实现的接口:
AutoCloseable , Executor , ExecutorService
已知子类:
ScheduledThreadPoolExecutor

public class ThreadPoolExecutor extends AbstractExecutorService
一个 ExecutorService ,它使用可能的几个池线程之一执行每个提交的任务,通常使用 Executors 工厂方法配置。

线程池解决了两个不同的问题:它们通常在执行大量异步任务时提供改进的性能,因为减少了每个任务的调用开销,并且它们提供了一种绑定和管理资源的方法,包括在执行一组异步任务时消耗的线程任务。每个ThreadPoolExecutor还维护一些基本的统计数据,比如完成任务的数量。

为了在广泛的上下文中发挥作用,此类提供了许多可调整的参数和可扩展性挂钩。但是,强烈建议程序员使用更方便的 Executors 工厂方法 Executors.newCachedThreadPool() (无界线程池,具有自动线程回收)、Executors.newFixedThreadPool(int) (固定大小线程池)和 Executors.newSingleThreadExecutor() (单后台线程),它们为最常见的使用场景预配置设置。否则,在手动配置和调整此类时使用以下指南:

核心和最大池大小
ThreadPoolExecutor 将根据 corePoolSize(参见 getCorePoolSize() )和 maximumPoolSize(参见 getMaximumPoolSize() )设置的边界自动调整池大小(参见 getPoolSize() )。当在方法 execute(Runnable) 中提交新任务时,如果正在运行的线程少于 corePoolSize ,则会创建一个新线程来处理请求,即使其他工作线程处于空闲状态也是如此。否则,如果运行的线程少于 maximumPoolSize,则只有在队列已满时才会创建一个新线程来处理请求。通过将 corePoolSize 和 maximumPoolSize 设置为相同,您可以创建一个固定大小的线程池。通过将 maximumPoolSize 设置为一个本质上无限制的值,例如 Integer.MAX_VALUE ,您允许池容纳任意数量的并发任务。最典型的是,核心和最大池大小仅在构造时设置,但它们也可以使用 setCorePoolSize(int) setMaximumPoolSize(int) 动态更改。
按需施工
默认情况下,即使是核心线程也仅在新任务到达时才最初创建和启动,但这可以使用方法 prestartCoreThread() prestartAllCoreThreads() 动态覆盖。如果您使用非空队列构建池,您可能希望预启动线程。
创建新线程
使用 ThreadFactory 创建新线程。如果没有另外指定,将使用 Executors.defaultThreadFactory() ,它创建的线程都处于相同的 ThreadGroup 并具有相同的 NORM_PRIORITY 优先级和非守护程序状态。通过提供不同的 ThreadFactory,您可以更改线程的名称、线程组、优先级、守护程序状态等。如果 ThreadFactory 在通过从 newThread 返回 null 询问时无法创建线程,执行程序将继续,但可能无法执行任何任务。线程应该拥有“modifyThread”RuntimePermission。如果工作线程或使用该池的其他线程不具备此权限,则服务可能会降级:配置更改可能无法及时生效,并且关闭的池可能仍处于可以终止但未完成的状态。
保活次数
如果池中当前有超过 corePoolSize 个线程,则多余的线程如果空闲时间超过 keepAliveTime(请参阅 getKeepAliveTime(TimeUnit) )将被终止。这提供了一种在池未被积极使用时减少资源消耗的方法。如果稍后池变得更加活跃,将构造新的线程。也可以使用方法 setKeepAliveTime(long, TimeUnit) 动态更改此参数。使用 Long.MAX_VALUE TimeUnit.NANOSECONDS 的值可以有效地禁止空闲线程在关闭之前终止。默认情况下,仅当线程数超过 corePoolSize 时才应用保持活动策略,但方法 allowCoreThreadTimeOut(boolean) 也可用于将此超时策略应用于核心线程,只要 keepAliveTime 值不为零即可。
排队
任何 BlockingQueue 可用于传输和保留提交的任务。此队列的使用与池大小交互:
  • 如果正在运行的线程少于 corePoolSize,则 Executor 总是更喜欢添加新线程而不是排队。
  • 如果 corePoolSize 或更多线程正在运行,则 Executor 总是更喜欢排队请求而不是添加新线程。
  • 如果请求无法排队,则会创建一个新线程,除非这会超过 maximumPoolSize,在这种情况下,任务将被拒绝。
排队的一般策略有以下三种:
  1. Direct handoffs. 工作队列的一个很好的默认选择是 SynchronousQueue ,它将任务交给线程而不用其他方式持有它们。在这里,如果没有线程立即可用于运行任务,尝试将任务排队将失败,因此将构造一个新线程。该策略在处理可能具有内部依赖性的请求集时避免了锁定。直接切换通常需要无限的 maximumPoolSizes 以避免拒绝新提交的任务。当命令的平均到达速度继续快于它们的处理速度时,这反过来又承认了无限线程增长的可能性。
  2. Unbounded queues. 使用无界队列(例如没有预定义容量的 LinkedBlockingQueue )将导致新任务在所有 corePoolSize 线程都忙时在队列中等待。因此,将永远不会创建超过 corePoolSize 个线程。 (因此 maximumPoolSize 的值没有任何影响。)当每个任务完全独立于其他任务时,这可能是合适的,因此任务不会影响彼此的执行;例如,在网页服务中。虽然这种排队方式可用于平滑请求的瞬态爆发,但它承认当命令继续以平均比处理速度更快的速度到达时,工作队列无限制增长的可能性。
  3. Bounded queues. 有界队列(例如 ArrayBlockingQueue )在与有限的 maximumPoolSizes 一起使用时有助于防止资源耗尽,但可能更难调整和控制。队列大小和最大池大小可以相互权衡:使用大队列和小池可以最大限度地减少 CPU 使用率、操作系统资源和上下文切换开销,但会导致吞吐量人为降低。如果任务频繁阻塞(例如,如果它们受 I/O 限制),系统可能会为比您允许的更多的线程安排时间。使用小队列通常需要更大的池大小,这会使 CPU 更忙,但可能会遇到无法接受的调度开销,这也会降低吞吐量。
拒绝的任务
当 Executor 关闭时,在方法 execute(Runnable) 中提交的新任务将是 rejected,并且当 Executor 对最大线程和工作队列容量使用有限边界并且饱和时。在任何一种情况下,execute 方法都会调用其 RejectedExecutionHandler RejectedExecutionHandler.rejectedExecution(Runnable, ThreadPoolExecutor) 方法。提供了四种预定义的处理程序策略:
  1. 在默认的 ThreadPoolExecutor.AbortPolicy 中,处理程序在拒绝时抛出运行时 RejectedExecutionException
  2. ThreadPoolExecutor.CallerRunsPolicy 中,调用 execute 的线程本身运行任务。这提供了一种简单的反馈控制机制,可以减慢提交新任务的速度。
  3. ThreadPoolExecutor.DiscardPolicy 中,无法执行的任务会被简单地丢弃。此策略仅适用于从不依赖任务完成的极少数情况。
  4. ThreadPoolExecutor.DiscardOldestPolicy 中,如果执行器未关闭,工作队列头部的任务将被丢弃,然后重试执行(可能会再次失败,导致重复。)这种策略很少被接受。在几乎所有情况下,您还应该取消任务以在任何等待其完成的组件中导致异常,和/或记录失败,如 ThreadPoolExecutor.DiscardOldestPolicy 文档中所示。
可以定义和使用其他类型的 RejectedExecutionHandler 类。这样做需要格外小心,尤其是当策略设计为仅在特定容量或排队策略下工作时。
钩子方法
此类提供 protected 可重写的 beforeExecute(Thread, Runnable) afterExecute(Runnable, Throwable) 方法,这些方法在执行每个任务之前和之后调用。这些可用于操纵执行环境;例如,重新初始化 ThreadLocals、收集统计信息或添加日志条目。此外,方法 terminated() 可以被覆盖以执行执行器完全终止后需要完成的任何特殊处理。

如果挂钩、回调或 BlockingQueue 方法抛出异常,则内部工作线程可能会依次失败、突然终止并可能被替换。

队列维护
方法 getQueue() 允许访问工作队列以进行监视和调试。强烈建议不要将此方法用于任何其他目的。当大量排队任务被取消时,提供的两个方法 remove(Runnable) purge() 可用于协助存储回收。
开垦
程序中不再引用的池 AND 没有剩余线程,可以在不显式关闭的情况下回收(垃圾收集)。您可以通过设置适当的保持活动时间、使用零核心线程的下限和/或设置 allowCoreThreadTimeOut(boolean) 来配置池以允许所有未使用的线程最终死亡。

扩展示例。此类的大多数扩展重写了一个或多个受保护的挂钩方法。例如,这是一个添加了简单的暂停/恢复功能的子类:

 
 class PausableThreadPoolExecutor extends ThreadPoolExecutor {
  private boolean isPaused;
  private ReentrantLock pauseLock = new ReentrantLock();
  private Condition unpaused = pauseLock.newCondition();

  public PausableThreadPoolExecutor(...) { super(...); }

  protected void beforeExecute(Thread t, Runnable r) {
   super.beforeExecute(t, r);
   pauseLock.lock();
   try {
    while (isPaused) unpaused.await();
   } catch (InterruptedException ie) {
    t.interrupt();
   } finally {
    pauseLock.unlock();
   }
  }

  public void pause() {
   pauseLock.lock();
   try {
    isPaused = true;
   } finally {
    pauseLock.unlock();
   }
  }

  public void resume() {
   pauseLock.lock();
   try {
    isPaused = false;
    unpaused.signalAll();
   } finally {
    pauseLock.unlock();
   }
  }
 } 
自从:
1.5
  • 构造方法详细信息

    • ThreadPoolExecutor

      public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit  unit, BlockingQueue <Runnable > workQueue)
      使用给定的初始参数、默认线程工厂默认拒绝执行处理程序 创建一个新的 ThreadPoolExecutor

      使用 Executors 工厂方法之一而不是这个通用构造函数可能更方便。

      参数:
      corePoolSize - 要保留在池中的线程数,即使它们处于空闲状态,除非设置了 allowCoreThreadTimeOut
      maximumPoolSize - 池中允许的最大线程数
      keepAliveTime - 当线程数大于核心时,这是多余空闲线程在终止前等待新任务的最长时间。
      unit - keepAliveTime 参数的时间单位
      workQueue - 在执行任务之前用于保存任务的队列。该队列将仅保存由 execute 方法提交的 Runnable 任务。
      抛出:
      IllegalArgumentException - 如果满足以下条件之一:
      corePoolSize < 0
      keepAliveTime < 0
      maximumPoolSize <= 0
      maximumPoolSize < corePoolSize
      NullPointerException - 如果 workQueue 为空
    • ThreadPoolExecutor

      public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit  unit, BlockingQueue <Runnable > workQueue, ThreadFactory  threadFactory)
      使用给定的初始参数和 默认拒绝执行处理程序 创建一个新的 ThreadPoolExecutor
      参数:
      corePoolSize - 要保留在池中的线程数,即使它们处于空闲状态,除非设置了 allowCoreThreadTimeOut
      maximumPoolSize - 池中允许的最大线程数
      keepAliveTime - 当线程数大于核心时,这是多余空闲线程在终止前等待新任务的最长时间。
      unit - keepAliveTime 参数的时间单位
      workQueue - 在执行任务之前用于保存任务的队列。该队列将仅保存由 execute 方法提交的 Runnable 任务。
      threadFactory - 执行程序创建新线程时使用的工厂
      抛出:
      IllegalArgumentException - 如果满足以下条件之一:
      corePoolSize < 0
      keepAliveTime < 0
      maximumPoolSize <= 0
      maximumPoolSize < corePoolSize
      NullPointerException - 如果 workQueuethreadFactory 为空
    • ThreadPoolExecutor

      public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit  unit, BlockingQueue <Runnable > workQueue, RejectedExecutionHandler  handler)
      使用给定的初始参数和 默认线程工厂 创建一个新的 ThreadPoolExecutor
      参数:
      corePoolSize - 要保留在池中的线程数,即使它们处于空闲状态,除非设置了 allowCoreThreadTimeOut
      maximumPoolSize - 池中允许的最大线程数
      keepAliveTime - 当线程数大于核心时,这是多余空闲线程在终止前等待新任务的最长时间。
      unit - keepAliveTime 参数的时间单位
      workQueue - 在执行任务之前用于保存任务的队列。该队列将仅保存由 execute 方法提交的 Runnable 任务。
      handler - 由于达到线程边界和队列容量而阻塞执行时使用的处理程序
      抛出:
      IllegalArgumentException - 如果满足以下条件之一:
      corePoolSize < 0
      keepAliveTime < 0
      maximumPoolSize <= 0
      maximumPoolSize < corePoolSize
      NullPointerException - 如果 workQueuehandler 为空
    • ThreadPoolExecutor

      public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit  unit, BlockingQueue <Runnable > workQueue, ThreadFactory  threadFactory, RejectedExecutionHandler  handler)
      使用给定的初始参数创建一个新的 ThreadPoolExecutor
      参数:
      corePoolSize - 要保留在池中的线程数,即使它们处于空闲状态,除非设置了 allowCoreThreadTimeOut
      maximumPoolSize - 池中允许的最大线程数
      keepAliveTime - 当线程数大于核心时,这是多余空闲线程在终止前等待新任务的最长时间。
      unit - keepAliveTime 参数的时间单位
      workQueue - 在执行任务之前用于保存任务的队列。该队列将仅保存由 execute 方法提交的 Runnable 任务。
      threadFactory - 执行程序创建新线程时使用的工厂
      handler - 由于达到线程边界和队列容量而阻塞执行时使用的处理程序
      抛出:
      IllegalArgumentException - 如果满足以下条件之一:
      corePoolSize < 0
      keepAliveTime < 0
      maximumPoolSize <= 0
      maximumPoolSize < corePoolSize
      NullPointerException - 如果 workQueuethreadFactoryhandler 为空
  • 方法详情

    • execute

      public void execute(Runnable  command)
      在将来的某个时间执行给定的任务。该任务可以在新线程或现有池线程中执行。如果任务无法提交执行,要么是因为这个执行器已经关闭,要么是因为它的容量已经达到,任务将由当前的 RejectedExecutionHandler 处理。
      参数:
      command - 要执行的任务
      抛出:
      RejectedExecutionException - 由 RejectedExecutionHandler 决定,如果任务不能被接受执行
      NullPointerException - 如果 command 为空
    • shutdown

      public void shutdown()
      启动有序关闭,其中执行先前提交的任务,但不会接受新任务。如果已经关闭,则调用没有额外效果。

      该方法不等待之前提交的任务完成执行。使用 awaitTermination 来做到这一点。

      抛出:
      SecurityException - 如果存在安全管理器并且关闭此 ExecutorService 可能会操作不允许调用者修改的线程,因为它不包含 RuntimePermission ("modifyThread") ,或者安全管理器的 checkAccess 方法拒绝访问。
    • shutdownNow

      public List <Runnable > shutdownNow()
      尝试停止所有正在执行的任务,停止等待任务的处理,并返回等待执行的任务列表。从此方法返回后,这些任务将从任务队列中排出(删除)。

      此方法不等待主动执行的任务终止。使用 awaitTermination 来做到这一点。

      除了尽最大努力停止处理正在执行的任务之外,没有任何保证。此实现通过 Thread.interrupt() 中断任务;任何未能响应中断的任务可能永远不会终止。

      返回:
      从未开始执行的任务列表
      抛出:
      SecurityException - 如果存在安全管理器并且关闭此 ExecutorService 可能会操作不允许调用者修改的线程,因为它不包含 RuntimePermission ("modifyThread") ,或者安全管理器的 checkAccess 方法拒绝访问。
    • isShutdown

      public boolean isShutdown()
      从接口 ExecutorService 复制的描述
      如果此执行程序已关闭,则返回 true
      返回:
      true 如果这个执行器已经关闭
    • isTerminating

      public boolean isTerminating()
      如果此执行程序在 shutdown() shutdownNow() 之后正在终止但尚未完全终止,则返回 true。此方法可能对调试有用。 true 的返回报告关闭后的足够时间可能表明提交的任务已忽略或抑制中断,导致此执行程序无法正确终止。
      返回:
      true 如果终止但尚未终止
    • isTerminated

      public boolean isTerminated()
      从接口 ExecutorService 复制的描述
      如果关闭后所有任务都已完成,则返回 true。请注意,除非先调用 shutdownshutdownNow,否则 isTerminated 永远不会是 true
      返回:
      true 如果关闭后所有任务都已完成
    • awaitTermination

      public boolean awaitTermination(long timeout, TimeUnit  unit) throws InterruptedException
      从接口 ExecutorService 复制的描述
      阻塞直到所有任务在关闭请求后完成执行,或者发生超时,或者当前线程被中断,以先发生者为准。
      参数:
      timeout - 最长时间等待
      unit - 超时参数的时间单位
      返回:
      true 如果此执行程序终止,false 如果超时在终止前结束
      抛出:
      InterruptedException - 如果在等待时被打断
    • finalize

      @Deprecated (since ="9", forRemoval =true) protected void finalize()
      已弃用,将被删除:此 API 元素可能会在未来版本中删除。
      Finalization 已被弃用以移除。有关迁移选项的背景信息和详细信息,请参阅 Object.finalize()
      从类复制的描述:Object
      当垃圾收集确定不再有对该对象的引用时,由垃圾收集器对该对象调用。子类覆盖 finalize 方法以处理系统资源或执行其他清理。

      在已禁用或删除终结的 Java 虚拟机中运行时,垃圾收集器永远不会调用 finalize() 。在启用终结的 Java 虚拟机中,垃圾收集器可能仅在无限期延迟后才调用 finalize

      finalize 的一般契约是,当 Java 虚拟机确定不再有任何方法可以通过任何尚未死亡的线程访问此对象时调用它,除非是采取操作的结果通过完成其他一些准备完成的对象或类。 finalize 方法可以采取任何行动,包括使该对象再次可用于其他线程;然而,finalize 的通常目的是在对象被不可撤销地丢弃之前执行清理操作。例如,表示输入/输出连接的对象的 finalize 方法可能会执行显式 I/O 事务以在对象被永久丢弃之前断开连接。

      Objectfinalize 方法不执行任何特殊操作;它只是正常返回。 Object 的子类可能会覆盖此定义。

      Java 编程语言不保证哪个线程将为任何给定对象调用 finalize 方法。但是,可以保证调用 finalize 的线程在调用 finalize 时不会持有任何用户可见的同步锁。如果 finalize 方法抛出未捕获的异常,则忽略该异常并终止该对象的终止。

      在为一个对象调用了finalize方法之后,不会采取进一步的行动,直到Java虚拟机再次确定不再有任何方法可以让任何尚未死亡的线程访问这个对象,包括可能的行动由准备完成的其他对象或类完成,此时该对象可能会被丢弃。

      对于任何给定对象,finalize 方法永远不会被 Java 虚拟机调用多次。

      finalize 方法抛出的任何异常都会导致此对象的终结停止,但会被忽略。

      重写:
      finalize 在类 Object
      实现注意事项:
      此类的早期版本有一个关闭此执行器的 finalize 方法,但在这个版本中,finalize 什么都不做。
      参见:
    • setThreadFactory

      public void setThreadFactory(ThreadFactory  threadFactory)
      设置用于创建新线程的线程工厂。
      参数:
      threadFactory - 新线程工厂
      抛出:
      NullPointerException - 如果 threadFactory 为空
      参见:
    • getThreadFactory

      public ThreadFactory  getThreadFactory()
      返回用于创建新线程的线程工厂。
      返回:
      当前线程工厂
      参见:
    • setRejectedExecutionHandler

      public void setRejectedExecutionHandler(RejectedExecutionHandler  handler)
      为不可执行的任务设置一个新的处理程序。
      参数:
      handler - 新的处理程序
      抛出:
      NullPointerException - 如果处理程序为空
      参见:
    • getRejectedExecutionHandler

      public RejectedExecutionHandler  getRejectedExecutionHandler()
      返回不可执行任务的当前处理程序。
      返回:
      当前处理程序
      参见:
    • setCorePoolSize

      public void setCorePoolSize(int corePoolSize)
      设置核心线程数。这会重写构造方法中设置的任何值。如果新值小于当前值,多余的现有线程将在下一次空闲时终止。如果更大,将在需要时启动新线程来执行任何排队的任务。
      参数:
      corePoolSize - 新的核心尺寸
      抛出:
      IllegalArgumentException - 如果 corePoolSize < 0corePoolSize 大于 最大池大小
      参见:
    • getCorePoolSize

      public int getCorePoolSize()
      返回核心线程数。
      返回:
      核心线程数
      参见:
    • prestartCoreThread

      public boolean prestartCoreThread()
      启动核心线程,使其空闲等待工作。这会覆盖仅在执行新任务时才启动核心线程的默认策略。如果所有核心线程都已启动,此方法将返回 false
      返回:
      true 如果线程已启动
    • prestartAllCoreThreads

      public int prestartAllCoreThreads()
      启动所有核心线程,使它们空闲等待工作。这会重写仅在执行新任务时才启动核心线程的默认策略。
      返回:
      启动的线程数
    • allowsCoreThreadTimeOut

      public boolean allowsCoreThreadTimeOut()
      如果此池允许核心线程超时并在 keepAlive 时间内没有任务到达时终止并在新任务到达时根据需要被替换,则返回 true。当为真时,应用于非核心线程的相同保持活动策略也适用于核心线程。当为 false(默认值)时,核心线程永远不会因缺少传入任务而终止。
      返回:
      true 如果允许核心线程超时,否则 false
      自从:
      1.6
    • allowCoreThreadTimeOut

      public void allowCoreThreadTimeOut(boolean value)
      如果在保持活动时间内没有任务到达,则设置核心线程是否可能超时并终止的策略,并在新任务到达时根据需要进行替换。当为 false 时,核心线程永远不会因缺少传入任务而终止。当为真时,适用于非核心线程的相同保持活动策略也适用于核心线程。为避免连续线程替换,设置 true 时保持活动时间必须大于零。通常应在主动使用池之前调用此方法。
      参数:
      value - true 如果应该超时,否则 false
      抛出:
      IllegalArgumentException - 如果值为 true 且当前保持活动时间不大于零
      自从:
      1.6
    • setMaximumPoolSize

      public void setMaximumPoolSize(int maximumPoolSize)
      设置允许的最大线程数。这会重写构造方法中设置的任何值。如果新值小于当前值,多余的现有线程将在下一次空闲时终止。
      参数:
      maximumPoolSize - 新的最大值
      抛出:
      IllegalArgumentException - 如果新最大值小于或等于零,或小于 核心池大小
      参见:
    • getMaximumPoolSize

      public int getMaximumPoolSize()
      返回允许的最大线程数。
      返回:
      最大允许线程数
      参见:
    • setKeepAliveTime

      public void setKeepAliveTime(long time, TimeUnit  unit)
      设置线程保持活动时间,这是线程在终止之前可以保持空闲的时间量。如果线程池中当前的线程数超过核心数量,或者如果此池 允许核心线程超时 ,则等待这段时间而不处理任务的线程将被终止。这会覆盖构造函数中设置的任何值。
      参数:
      time - 等待的时间。时间值为零将导致多余的线程在执行任务后立即终止。
      unit - time 参数的时间单位
      抛出:
      IllegalArgumentException - 如果 time 小于零或如果 time 为零且 allowsCoreThreadTimeOut
      参见:
    • getKeepAliveTime

      public long getKeepAliveTime(TimeUnit  unit)
      返回线程保持活动时间,这是线程在终止之前可以保持空闲的时间量。如果线程池中当前的线程数超过核心数量,或者如果此池 允许核心线程超时 ,则等待这段时间而不处理任务的线程将被终止。
      参数:
      unit - 结果所需的时间单位
      返回:
      时限
      参见:
    • getQueue

      public BlockingQueue <Runnable > getQueue()
      返回此执行程序使用的任务队列。访问任务队列主要用于调试和监控。该队列可能正在使用中。检索任务队列不会阻止排队任务的执行。
      返回:
      任务队列
    • remove

      public boolean remove(Runnable  task)
      如果此任务存在,则从执行程序的内部队列中删除此任务,从而使其在尚未启动时不运行。

      该方法可用作取消方案的一部分。它可能无法删除在放入内部队列之前已转换为其他形式的任务。例如,使用 submit 输入的任务可能会转换为保持 Future 状态的形式。然而,在这种情况下,方法 purge() 可用于删除那些已取消的 Futures。

      参数:
      task - 要删除的任务
      返回:
      true 如果任务被删除
    • purge

      public void purge()
      尝试从工作队列中删除所有已取消的 Future 任务。此方法可用作存储回收操作,对功能没有其他影响。取消的任务永远不会执行,但可能会在工作队列中累积,直到工作线程可以主动删除它们。现在调用此方法会尝试删除它们。但是,此方法可能无法在存在其他线程干扰的情况下删除任务。
    • getPoolSize

      public int getPoolSize()
      返回池中的当前线程数。
      返回:
      线程数
    • getActiveCount

      public int getActiveCount()
      返回正在执行任务的线程的大概数量。
      返回:
      线程数
    • getLargestPoolSize

      public int getLargestPoolSize()
      返回池中曾经同时存在的最大线程数。
      返回:
      线程数
    • getTaskCount

      public long getTaskCount()
      返回已安排执行的任务的大致总数。由于任务和线程的状态在计算过程中可能会动态变化,因此返回值只是一个近似值。
      返回:
      任务数
    • getCompletedTaskCount

      public long getCompletedTaskCount()
      返回已完成执行的任务的大致总数。因为任务和线程的状态可能在计算过程中动态变化,所以返回值只是一个近似值,但不会在连续调用中减少。
      返回:
      任务数
    • toString

      public String  toString()
      返回标识此池及其状态的字符串,包括运行状态和估计的工作人员和任务计数的指示。
      重写:
      toString 在类 Object
      返回:
      标识此池及其状态的字符串
    • beforeExecute

      protected void beforeExecute(Thread  t, Runnable  r)
      在给定线程中执行给定的 Runnable 之前调用的方法。此方法由将执行任务 r 的线程 t 调用,可用于重新初始化 ThreadLocals,或执行日志记录。

      这个实现什么都不做,但可以在子类中定制。注意:为了正确嵌套多个覆盖,子类通常应该在此方法的末尾调用 super.beforeExecute

      参数:
      t - 将运行任务 r 的线程
      r - 将要执行的任务
    • afterExecute

      protected void afterExecute(Runnable  r, Throwable  t)
      在给定的 Runnable 执行完成时调用的方法。此方法由执行任务的线程调用。如果非空,则 Throwable 是导致执行突然终止的未捕获的 RuntimeExceptionError

      这个实现什么都不做,但可以在子类中定制。注意:要正确嵌套多个重写,子类通常应在此方法的开头调用 super.afterExecute

      笔记:当操作(例如 FutureTask )显式地或通过 submit 等方法包含在任务中时,这些任务对象捕获并维护计算异常,因此它们不会导致突然终止,并且内部异常被 not 传递给此方法。如果您想在此方法中捕获这两种失败,您可以进一步探测此类情况,如在这个示例子类中打印直接原因或底层异常(如果任务已中止):

       
       class ExtendedExecutor extends ThreadPoolExecutor {
        // ...
        protected void afterExecute(Runnable r, Throwable t) {
         super.afterExecute(r, t);
         if (t == null
           && r instanceof Future<?>
           && ((Future<?>)r).isDone()) {
          try {
           Object result = ((Future<?>) r).get();
          } catch (CancellationException ce) {
           t = ce;
          } catch (ExecutionException ee) {
           t = ee.getCause();
          } catch (InterruptedException ie) {
           // ignore/reset
           Thread.currentThread().interrupt();
          }
         }
         if (t != null)
          System.out.println(t);
        }
       } 
      参数:
      r - 已完成的可运行对象
      t - 导致终止的异常,如果执行正常完成则为 null
    • terminated

      protected void terminated()
      Executor 终止时调用的方法。默认实现什么也不做。注意:为了正确嵌套多个覆盖,子类通常应该在此方法中调用 super.terminated