【问题标题】:Why is a Runnable still executed in a pausable thread pool executor after the executor is shut down?为什么执行器关闭后,一个可暂停的线程池执行器仍然执行一个Runnable?
【发布时间】:2017-06-22 12:19:48
【问题描述】:

我有一个可暂停的线程池执行器实现,就像在 ThreadPoolExecutor 类的文档中一样。我有一个简单的测试,它执行以下操作:

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 将尝试通过中断主动执行的任务来停止它们。但是中断似乎唤醒了任务并执行它。有人可以解释一下吗?

【问题讨论】:

  • 当您要求关闭时,它会中断工作线程,但这并不意味着它会立即停止。这取决于逻辑以及您在代码中使用中断标志的方式

标签: java multithreading threadpool


【解决方案1】:

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

不确定它是否“正常”,但考虑到您的代码,它肯定是可以预期的。在您的 beforeExecute(...) 方法中,我看到以下内容:

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

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

如果您想在作业被中断时停止作业,那么当您看到作业被中断时,您可以在 beforeExecute() 处理程序中抛出 RuntimeException

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

一种更简洁的方法可能是检查您是否在run() 方法中被打断,然后退出:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-05
    • 2015-11-17
    • 1970-01-01
    • 1970-01-01
    • 2014-08-27
    • 2017-12-29
    相关资源
    最近更新 更多