模块  java.base
软件包  java.util.concurrent

Class ThreadPoolExecutor

  • 实现的所有接口
    ExecutorExecutorService
    已知直接子类:
    ScheduledThreadPoolExecutor

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

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

    为了在各种上下文中有用,该类提供了许多可调参数和可扩展性钩子。 但是,程序员被要求使用更方便的Executors工厂方法Executors.newCachedThreadPool() (无界线程池,具有自动线程回收), Executors.newFixedThreadPool(int) (固定大小线程池)和Executors.newSingleThreadExecutor() (单个后台线程),为最常见的使用场景预配置设置。 否则,在手动配置和调整此类时,请使用以下指南:

    核心和最大池大小
    ThreadPoolExecutor将自动调整池大小(见getPoolSize()根据corePoolSize(参见设定的界限) getCorePoolSize() )和maximumPoolSize(参见getMaximumPoolSize() )。 在方法execute(Runnable)提交新任务时,如果正在运行少于corePoolSize线程,则会创建一个新线程来处理该请求,即使其他工作线程处于空闲状态也是如此。 否则,如果正在运行少于maximumPoolSize的线程,则只有在队列已满时才会创建新线程来处理请求。 通过设置corePoolSize和maximumPoolSize相同,您可以创建固定大小的线程池。 通过将Integer.MAX_VALUE设置为基本无限制的值(例如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线程时,保持活动策略才适用,但只要keepAliveTime值为非零,方法allowCoreThreadTimeOut(boolean)也可用于将此超时策略应用于核心线程。
    排队
    任何BlockingQueue都可用于传输和保留提交的任务。 此队列的使用与池大小调整交互:
    • 如果运行的corePoolSize线程少于corePoolSize,则Executor总是更喜欢添加新线程而不是排队。
    • 如果corePoolSize或更多线程正在运行,则Executor总是更喜欢排队请求而不是添加新线程。
    • 如果请求无法排队,则会创建一个新线程,除非它超过maximumPoolSize,在这种情况下,该任务将被拒绝。
    排队有三种常规策略:
    1. 直接交接。 工作队列的一个很好的默认选择是SynchronousQueue ,它可以将任务交给线程,而不会保留它们。 在这里,如果没有线程立即可用于运行它,则尝试对任务进行排队将失败,因此将构造新线程。 此策略在处理可能具有内部依赖性的请求集时避免了锁定。 直接切换通常需要无限制的maximumPoolSizes以避免拒绝新提交的任务。 这反过来承认,当命令继续以比处理它们更快的速度到达时,无限制的线程增长的可能性。
    2. 无限队列。 使用无界队列(例如,没有预定义容量的LinkedBlockingQueue )将导致新任务在所有corePoolSize线程忙时在队列中等待。 因此,只会创建corePoolSize线程。 (并且maximumPoolSize的值因此没有任何影响。)当每个任务完全独立于其他任务时,这可能是适当的,因此任务不会影响彼此的执行; 例如,在网页服务器中。 虽然这种排队方式可以有助于平滑瞬态突发请求,但它承认,当命令继续平均到达的速度超过可处理速度时,无限制的工作队列增长的可能性。
    3. 有限的队列。 有限队列(例如, ArrayBlockingQueue )在与有限maximumPoolSizes一起使用时有助于防止资源耗尽,但可能更难以调整和控制。 队列大小和最大池大小可以相互交换:使用大型队列和小型池最小化CPU使用率,OS资源和上下文切换开销,但可能导致人为的低吞吐量。 如果任务经常阻塞(例如,如果它们是I / O绑定的),则系统可能能够为您提供比您允许的更多线程的时间。 使用小队列通常需要更大的池大小,这会使CPU更加繁忙,但可能会遇到不可接受的调度开销,这也会降低吞吐量。
    被拒绝的任务
    当Executor关闭时,以及当Executor对最大线程和工作队列容量使用有限边界并且已经饱和时,将拒绝方法execute(Runnable)提交的新任务。 在任何一种情况下, execute方法都会调用其RejectedExecutionHandlerRejectedExecutionHandler.rejectedExecution(Runnable, ThreadPoolExecutor)方法。 提供了四种预定义的处理程序策
    1. 在默认值ThreadPoolExecutor.AbortPolicy ,处理程序在拒绝时抛出运行时RejectedExecutionException
    2. ThreadPoolExecutor.CallerRunsPolicy ,调用execute的线程本身运行该任务。 这提供了一种简单的反馈控制机制,可以降低新任务的提交速度。
    3. ThreadPoolExecutor.DiscardPolicy ,简单地删除了无法执行的任务。
    4. ThreadPoolExecutor.DiscardOldestPolicy ,如果执行程序未关闭,则会删除工作队列头部的任务,然后重试执行(可能会再次失败,导致重复执行)。
    可以定义和使用其他类型的RejectedExecutionHandler类。 这样做需要一些小心,特别是当策略设计为仅在特定容量或排队策略下工作时。
    钩子方法
    此类提供protected覆盖的beforeExecute(Thread, Runnable)afterExecute(Runnable, Throwable)方法,这些方法在执行每个任务之前和之后调用。 这些可以用来操纵执行环境; 例如,重新初始化ThreadLocals,收集统计信息或添加日志条目。 另外,可以重写方法terminated()以执行在Executor完全终止后需要完成的任何特殊处理。

    如果hook,callback或BlockingQueue方法抛出异常,内部工作线程可能会失败,突然终止,并可能被替换。

    队列维护
    方法getQueue()允许访问工作队列以进行监视和调试。 强烈建议不要将此方法用于任何其他目的。 当大量排队任务被取消时,两种提供的方法remove(Runnable)purge()可用于协助存储回收。
    开垦
    即不再在程序中引用也没有剩余线程都可以被回收(垃圾回收)没有被明确地关闭池。 您可以通过设置适当的保持活动时间,使用零核心线程的下限和/或设置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 - 池中保留的线程数,即使它们处于空闲状态,除非 allowCoreThreadTimeOutallowCoreThreadTimeOut
        maximumPoolSize - 池中允许的最大线程数
        keepAliveTime - 当线程数大于核心数时,这是多余空闲线程在终止之前等待新任务的最长时间。
        unit - keepAliveTime参数的时间单位
        workQueue - 在执行任务之前用于保存任务的队列。 此队列仅Runnable 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给定的初始参数和default rejected execution handler
        参数
        corePoolSize - 池中保留的线程数,即使它们处于空闲状态,除非设置了 allowCoreThreadTimeOut
        maximumPoolSize - 池中允许的最大线程数
        keepAliveTime - 当线程数大于核心数时,这是多余空闲线程在终止之前等待新任务的最长时间。
        unit - keepAliveTime参数的时间单位
        workQueue - 在执行任务之前用于保存任务的队列。 此队列仅Runnable 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给定的初始参数和 default thread factory
        参数
        corePoolSize - 池中保留的线程数,即使它们处于空闲状态,除非设置了 allowCoreThreadTimeOut
        maximumPoolSize - 池中允许的最大线程数
        keepAliveTime - 当线程数大于核心数时,这是多余空闲线程在终止之前等待新任务的最长时间。
        unit - keepAliveTime参数的时间单位
        workQueue - 在执行任务之前用于保存任务的队列。 此队列仅Runnable 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 - 在执行任务之前用于保存任务的队列。 此队列仅Runnable 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可能会操纵不允许调用者修改的线程,因为它不包含 ("modifyThread") ,或者安全管理器的checkAccess方法拒绝访问。
      • shutdownNow

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

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

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

        结果
        从未开始执行的任务列表
        异常
        SecurityException - 如果存在安全管理器并关闭此ExecutorService,则可以操纵不允许调用者修改的线程,因为它不存在RuntimePermission ("modifyThread") ,或者安全管理器的checkAccess方法拒绝访问。
      • isTerminating

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

        @Deprecated(since="9")protected void finalize()
        Deprecated.
        复制自类的说明: Object
        当垃圾收集确定没有对该对象的更多引用时,由对象上的垃圾收集器调用。 子类重写finalize方法以处置系统资源或执行其他清理。

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

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

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

        在为对象调用finalize方法之后,在Java虚拟机再次确定不再有任何方法可以通过任何尚未死亡的线程访问此对象(包括可能的操作)之前,不会采取进一步操作通过准备完成的其他对象或类,此时可以丢弃该对象。

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

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

        重写:
        finalize在类 Object
        Implementation Note:
        此类的早期版本具有关闭此执行程序的finalize方法,但在此版本中,finalize不执行任何操作。
        另请参见:
        WeakReferencePhantomReference
      • setThreadFactory

        public void setThreadFactory​(ThreadFactory threadFactory)
        设置用于创建新线程的线程工厂。
        参数
        threadFactory - 新的线程工厂
        异常
        NullPointerException - 如果threadFactory为null
        另请参见:
        getThreadFactory()
      • setCorePoolSize

        public void setCorePoolSize​(int corePoolSize)
        设置核心线程数。 这将覆盖构造函数中设置的任何值。 如果新值小于当前值,则当下一个空闲时,将终止多余的现有线程。 如果需要更大,则新线程将启动以执行任何排队任务。
        参数
        corePoolSize - 新的核心尺寸
        异常
        IllegalArgumentException - 如果 corePoolSize < 0corePoolSize大于 maximum pool size
        另请参见:
        getCorePoolSize()
      • getCorePoolSize

        public int getCorePoolSize()
        返回核心线程数。
        结果
        核心线程数
        另请参见:
        setCorePoolSize(int)
      • prestartCoreThread

        public boolean prestartCoreThread()
        启动一个核心线程,导致它无所事事地等待工作。 这将覆盖仅在执行新任务时启动核心线程的默认策略。 如果所有核心线程都已启动,则此方法将返回false
        结果
        true如果线程已启动
      • prestartAllCoreThreads

        public int prestartAllCoreThreads()
        启动所有核心线程,导致它们无所事事地等待工作。 这将覆盖仅在执行新任务时启动核心线程的默认策略。
        结果
        线程数已启动
      • allowsCoreThreadTimeOut

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

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

        public void setMaximumPoolSize​(int maximumPoolSize)
        设置允许的最大线程数。 这将覆盖构造函数中设置的任何值。 如果新值小于当前值,则当下一个空闲时,将终止多余的现有线程。
        参数
        maximumPoolSize - 新的最大值
        异常
        IllegalArgumentException - 如果新的最大值小于或等于零,或小于 core pool size
        另请参见:
        getMaximumPoolSize()
      • getMaximumPoolSize

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

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

        public long getKeepAliveTime​(TimeUnit unit)
        返回线程保持活动时间,它是线程在终止之前保持空闲的时间量。 如果池中当前有多个线程核心,或者此池allows core thread timeout ,则将终止等待此时间而不处理任务的线程。
        参数
        unit - 结果的所需时间单位
        结果
        时间限制
        另请参见:
        setKeepAliveTime(long, TimeUnit)
      • getQueue

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

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

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

        参数
        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 ,子类通常应在此方法结束时调用super.beforeExecute

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

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

        此实现不执行任何操作,但可以在子类中进行自定义。 注意:要正确嵌套多个super.afterExecute ,子类通常应在此方法的开头调用super.afterExecute

        注意:当任务明确地或通过诸如submit方法包含在任务(例如FutureTask )中时,这些任务对象会捕获并维护计算异常,因此它们不会导致突然终止,并且内部异常不会传递给此方法。 如果您希望在此方法中捕获两种类型的故障,则可以进一步探测此类情况,如此示例子类中,如果任务已中止,则会打印直接原因或基础异常:

           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 - 已完成的runnable
        t - 导致终止的异常,如果执行正常,则返回null
      • terminated

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