【问题标题】:Polling empty queue - JCIP listing 7.7轮询空队列 - JCIP 清单 7.7
【发布时间】:2018-01-17 20:35:53
【问题描述】:

在这个code

public class NoncancelableTask {
    public Task getNextTask(BlockingQueue<Task> queue) {
        boolean interrupted = false;
        try {
            while (true) {
                try {
                    return queue.take();
                } catch (InterruptedException e) {
                    interrupted = true;
                    // fall through and retry
                }
            }
        } finally {
            if (interrupted)
                Thread.currentThread().interrupt();
        }
    }

    interface Task {
    }
}

如果队列已经为空怎么办?代码会吞下第一个异​​常,然后重试——然后永远等待? 我认为中断的主要思想是取消任务,如果它卡在一些阻塞方法上,如 Thread.sleep、BlockingQueue.take() 等。

有类似的问题What is the point of restoring the interrupted status in JCIP listing 7.7?,但我没有足够的声誉发表评论

【问题讨论】:

    标签: java multithreading concurrency interrupted-exception


    【解决方案1】:

    中断点不是取消,在考虑中断逻辑时,两者应该分开。中断可以用于取消,但如上面的示例中,它也可以被忽略。

    可能是getNextTask(...) 返回的任务非常重要,以至于线程在中断时无法退出。因此,线程将保持阻塞状态,直到队列中有任务可用,除非程序完全死掉或遇到灾难性错误。

    同样,这不是无限期地等待,只是直到有可用的任务。这个示例的重要之处在于它在返回时包含一个布尔检查,它将把中断传递给调用线程。这样,当线程最终解除阻塞时,可以检查中断以使其在必要时退出。

    【讨论】:

      【解决方案2】:

      queue.take() 会等到有东西要取。没有任何东西抛出 InterruptedExcpetion 因此 catch 块不会执行。您将一直留在 try 块中,直到将某些内容添加到 que 或引发中断的异常。

      Thread.currentThread().interrupt(),除非我错了,否则不会做太多,因为你的代码现在是单线程的,如果它在 finally 块中,那么该单线程已经超出了 try 块.

      这里是一个如何使用中断的例子:

      public class StoppingThreads implements Runnable
      {
      
      
      public static void main(String[] args)     
      {
          Thread t0 = new Thread(new StoppingThreads());
          t0.start();
          Thread t1= new Thread(new StoppingThreads());
          t1.start();
          Thread t2 = new Thread(new StoppingThreads());
          t2.start();
          Thread t3 = new Thread(new StoppingThreads());
          t3.start();
          Thread t4 = new Thread(new StoppingThreads());
          t4.start();
          System.out.println("All threads started");
          t0.interrupt();
          t1.interrupt();
      
      }
      
      @Override
      public void run() 
      {
          try {
              Thread.sleep(5000);
          } catch (InterruptedException ex) {
      
          }
      
          System.out.println(Thread.currentThread().getName() + " Finished");
      }
      
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多