Module  java.base
软件包  java.util.concurrent

Class ThreadPoolExecutor

  • All Implemented Interfaces:
    ExecutorExecutorService
    已知直接子类:
    ScheduledThreadPoolExecutor


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

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

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

    核心和最大池大小
    ThreadPoolExecutor将自动调整池大小(见getPoolSize()根据corePoolSize(参见设定的界限) getCorePoolSize() )和maximumPoolSize(参见getMaximumPoolSize() )。 当方法execute(Runnable)提交了新任务,并且运行的corePoolSize线程少于一个,即使其他工作线程处于空闲状态,也会创建一个新的线程来处理该请求。 如果超过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线程正在运行,Executor总是喜欢添加一个新线程,而不是排队。
    • 如果corePoolSize或更多的线程正在运行,Executor总是喜欢排队请求而不是添加一个新的线程。
    • 如果请求无法排队,则会创建一个新线程,除非这将超过maximumPoolSize,否则任务将被拒绝。
    排队有三种一般策略:
    1. 直接切换 一个工作队列的一个很好的默认选择是一个SynchronousQueue ,它将任务交给线程,而不用其他任务。 在这里,如果没有线程可以立即运行,那么尝试排队任务会失败,因此将构建一个新的线程。 处理可能具有内部依赖关系的请求集时,此策略可避免锁定。 直接切换通常需要无限制的maximumPoolSizes,以避免拒绝新提交的任务。 这反过来允许无限线程增长的可能性,当命令继续以平均速度比他们可以处理的速度更快地到达时。
    2. 无界队列 当所有corePoolSize线程都忙时,使用无界队列(例如没有预定义容量的LinkedBlockingQueue )将导致新任务在队列中等待。 因此,不会再创建corePoolSize线程。 (因此,最大值大小的值没有任何影响。)每个任务完全独立于其他任务时,这可能是适当的,因此任务不会影响其他执行; 例如,在网页服务器中。 虽然这种排队风格可以有助于平滑瞬态突发的请求,但是当命令继续达到的平均速度比可以处理的速度更快时,它承认无界工作队列增长的可能性。
    3. 有边界的队列。 有限队列(例如, ArrayBlockingQueue )有助于防止在使用有限maxPoolSizes时耗尽资源,但可能更难调整和控制。 队列大小和最大池大小可能彼此交易:使用大队列和小型池可以最大限度地减少CPU使用率,OS资源和上下文切换开销,但可能导致人为的低吞吐量。 如果任务频繁阻塞(例如,如果它们是I / O绑定),则系统可能能够安排比您允许的更多线程的时间。 使用小型队列通常需要较大的池大小,这样可以使CPU繁忙,但可能会遇到不可接受的调度开销,这也降低了吞吐量。
    被拒绝的任务
    方法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()可以被覆盖,以执行执行者完全终止后需要执行的任何特殊处理。

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

    队列维护
    方法getQueue()允许访问工作队列以进行监视和调试。 强烈不鼓励将此方法用于任何其他目的。 两个提供的方法, remove(Runnable)purge()可用于在大量排队任务被取消时协助进行存储回收。
    定稿
    即不再在程序中引用, 没有剩余的线程将成为池shutdown自动。 如果您希望确保未引用的池被回收,即使用户忘记调用shutdown() ,则必须通过使用零个核心线程的下限和/或设置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 - 如果以下 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 - 在执行任务之前用于保存任务的队列。 该队列将仅Runnable execute方法提交的Runnable任务。
        threadFactory - 在执行程序创建新线程时使用的工厂
        异常
        IllegalArgumentException - 如果以下 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 - 在执行任务之前用于保存任务的队列。 该队列将仅Runnable execute方法提交的Runnable任务。
        threadFactory - 当执行程序创建新线程时使用的工厂
        handler - 执行被阻止时使用的处理程序,因为达到线程限制和队列容量
        异常
        IllegalArgumentException - 如果以下条件之一成立:
        corePoolSize < 0
        keepAliveTime < 0
        maximumPoolSize <= 0
        maximumPoolSize < corePoolSize
        NullPointerException - 如果 workQueuethreadFactoryhandler为null
    • 方法详细信息

      • 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 请注意, isTerminated从不是true除非首先调用了shutdownshutdownNow
        结果
        true如果所有任务在关闭后都已完成
      • awaitTermination

        public boolean awaitTermination​(long timeout,
                                        TimeUnit unit)
                                 throws InterruptedException
        描述从接口ExecutorService复制
        阻止所有任务在关闭请求完成后执行,或发生超时或当前线程中断,以先到者为准。
        参数
        timeout - 等待的最长时间
        unit - 超时参数的时间单位
        结果
        true如果这个执行者终止了,并且终止之前超时的时间是 false
        异常
        InterruptedException - 如果在等待时中断
      • finalize

        @Deprecated(since="9")
        protected void finalize​()
        已过时。 finalize方法已被弃用。 为了执行清理,覆盖finalize子类应被修改为使用替代的清理机制,并删除覆盖的finalize方法。 当覆盖finalize方法时,其实现必须明确确保按照super.finalize()中所述调用super.finalize() 有关迁移选项的更多信息,请参阅Object.finalize()的规范。
        当这个执行器不再被引用并且没有线程时,调用 shutdown
        重写:
        finalizeObject
        另请参见:
        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)
        设置策略是否核心线程可能会超时,如果任务没有在活着的时间内到达,则在新任务到达时被替换。 当虚假时,由于缺少传入任务,核心线程不会终止。 当为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​()
        返回标识此池的字符串及其状态,包括运行状态和估计的工作人员和任务计数的指示。
        重写:
        toStringObject
        结果
        一个标识这个池的字符串,以及它的状态
      • beforeExecute

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

        此实现不执行任何操作,但可以在子类中进行自定义。 注意:为了正确嵌套多个覆盖,子类应通常在此方法结束时调用super.beforeExecute

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

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

        此实现不执行任何操作,但可以在子类中进行自定义。 注意:为了正确嵌套多个覆盖,子类应该在此方法开始时调用super.afterExecute

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

           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​()
        Method invoked when the Executor has terminated. Default implementation does nothing. Note: To properly nest multiple overridings, subclasses should generally invoke super.terminated within this method.