执行程序关闭后,为什么Runnable仍然在可执行的线程池执行程序中执行?

问题描述:

我有一个可以使用的线程池执行程序实现,就像在ThreadPoolExecutor类的文档中一样。我有一个简单的测试执行以下操作:执行程序关闭后,为什么Runnable仍然在可执行的线程池执行程序中执行?

class PausableThreadPoolExecutor extends ThreadPoolExecutor { 
    public static PausableThreadPoolExecutor newSingleThreadExecutor() { 
    return new PausableThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, 
     new LinkedBlockingQueue<Runnable>()); 
    } 

    /** isPaused */ 
    private boolean isPaused; 

    /** pauseLock */ 
    private ReentrantLock pauseLock = new ReentrantLock(); 

    /** unpaused */ 
    private Condition unpaused = this.pauseLock.newCondition(); 

    public PausableThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, 
     TimeUnit unit, BlockingQueue<Runnable> workQueue) { 
    super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue); 
    } 

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

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

    public void resume() { 
    this.pauseLock.lock(); 
    try { 
     this.isPaused = false; 
     this.unpaused.signalAll(); 
    } finally { 
     this.pauseLock.unlock(); 
    } 
    } 

    public static void main(String[] args) { 
    PausableThreadPoolExecutor p = PausableThreadPoolExecutor.newSingleThreadExecutor(); 
    p.pause(); 
    p.execute(new Runnable() { 

     public void run() { 
     for (StackTraceElement ste : Thread.currentThread().getStackTrace()) { 
      System.out.println(ste); 
     } 
     } 
    }); 
    p.shutdownNow(); 
    } 
} 

有趣的是调用shutdownNow时会引起了Runnable运行。这是正常的吗?据我了解,shutDownNow将尝试通过中断它们来停止正在执行的任务。但中断似乎唤醒了执行它的任务。有人可以解释这个吗?

+0

当你调用关机是中断工作者线程,这并不意味着它会立即停止。它取决于逻辑,以及如何使用间代码中的破裂标志 –

有趣的是,对shutDownNow的调用将导致Runnable运行。这是正常的吗?

不确定这是“正常”,但它肯定会给你的代码。在你beforeExecute(...)方法我看到以下内容:

this.pauseLock.lock(); 
    try { 
     while (this.isPaused) { 
      this.unpaused.await(); 
     } 
    } catch (InterruptedException ie) { 
     t.interrupt(); 
    } finally { 
     this.pauseLock.unlock(); 
    } 

作业将LOPP等待isPaused布尔值设置为false。但是,如果作业中断,则this.unpaused.await()将抛出InterruptedException,这突破while循环,线程将重新中断,这总是一个好的模式,返回beforeExecute(),并允许执行作业。除非你有特定的代码来处理中断,否则中断一个线程不会中止它。

如果要停止作业时被中断,那么你可以扔RuntimeExceptionbeforeExecute()处理程序,当你看到作业作为被中断:

} catch (InterruptedException ie) { 
    t.interrupt(); 
    throw new RuntimeException("Thread was interrupted so don't run"); 

一个清洁的方法可能是检查看看你是在run()方法打断,然后退出:

public void run() { 
    if (Thread.currentThread().isInterrupted()) { 
     return; 
    } 
    ... 
+0

清除,谢谢你的回应。 –