【问题标题】:how java thead pool executor deals with interrupted threadjava线程池执行器如何处理中断线程
【发布时间】:2016-06-01 11:43:50
【问题描述】:

我创建了一个ThreadPool,其中包含 10 个固定线程。有时我需要中断线程池中一个长时间运行的线程,主要是因为它们在某些操作中阻塞并且发生超时并且我中断了线程。我抓住了InterruptedException 并将线程的状态也设置为中断。在这种情况下,我的问题是,ThreadPool 是否会创建一个新线程并用新的 One 替换中断的线程? 下面是由线程执行的示例代码。问题是,当这个线程被中断时,线程池会用一个新的线程替换这个线程吗?

 public ResponseMessage call(){
    Future<ResponseMessage> future = CacheManager.getInstance().asyncFetch();
    ResponseMessage response = null;
    try {
        response = future.get();
    }
    catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    } catch (ExecutionException ex) {
        //create a blank response
    }

    return response;
}

【问题讨论】:

  • 你用的是什么线程池?
  • 你知道get() 有一个可以接受超时的重载,对吧?
  • 请忽略秒表,是的,我知道 get with time-out 方法。

标签: java threadpool


【解决方案1】:

您不应中断不属于您“拥有”的线程,因为您不知道它们如何响应。由于您无法控制线程调度,因此您真的不知道给定线程在您中断它的那一刻正在执行特定任务

如果您想取消您已提供执行程序服务的任务,请在其关联的Future 上调用cancel(true)。当您的任务检测到中断请求时,它应该通过调用Thread.currentThread().interrupt() 来保持中断状态。

如果你这样做,执行器会干净地处理中断,因为它自己中断了线程,并且知道在中断发生时线程正在执行任务。

【讨论】:

  • 我完全按照你所说的,我取消了未来,在被调用线程中,我保留了中断的状态。
  • 上面代码有一个调用者,将这个可调用的任务提交给线程池,并使用future.cancel(true)取消该任务
  • 那你应该没事了。虽然在另一个任务中使用了Future,但代码看起来很奇怪,所以我怀疑事情可以大大简化。
【解决方案2】:

从一步一步的调试来看,我想被中断的线程会继续从工作队列中获取任务。 中断状态在getTask之前已经清理完毕。

例如,如果您将 FixedThreadPool 与 LinkedBlockingQueue 一起使用,则中断状态会在 queue.take() 内部被 ReentrantLock.lockInterruptibly() 清除

public final void acquireInterruptibly(int arg) throws InterruptedException {
    if (**Thread.interrupted()**)
        throw new InterruptedException();
    if (!tryAcquire(arg))
         doAcquireInterruptibly(arg);
}

【讨论】:

    猜你喜欢
    • 2014-08-27
    • 2017-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 2021-04-11
    • 1970-01-01
    相关资源
    最近更新 更多