如何中断阻塞 take() 上的阻塞队列?

2022-08-31 11:25:09

我有一个类,它从 a 中获取对象,并通过在连续循环中调用来处理它们。在某些时候,我知道不会再有对象被添加到队列中。如何中断方法以使其停止阻塞?BlockingQueuetake()take()

下面是处理对象的类:

public class MyObjHandler implements Runnable {

  private final BlockingQueue<MyObj> queue;

  public class MyObjHandler(BlockingQueue queue) {
    this.queue = queue;
  }

  public void run() {
    try {
      while (true) {
        MyObj obj = queue.take();
        // process obj here
        // ...
      }
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
    }
  }
}

下面是使用此类处理对象的方法:

public void testHandler() {

  BlockingQueue<MyObj> queue = new ArrayBlockingQueue<MyObj>(100);  

  MyObjectHandler  handler = new MyObjectHandler(queue);
  new Thread(handler).start();

  // get objects for handler to process
  for (Iterator<MyObj> i = getMyObjIterator(); i.hasNext(); ) {
    queue.put(i.next());
  }

  // what code should go here to tell the handler
  // to stop waiting for more objects?
}

答案 1

如果中断线程不是一个选项,另一种方法是在队列上放置一个“标记”或“命令”对象,MyObjHandler会识别这些对象并中断循环。


答案 2
BlockingQueue<MyObj> queue = new ArrayBlockingQueue<MyObj>(100);
MyObjectHandler handler = new MyObjectHandler(queue);
Thread thread = new Thread(handler);
thread.start();
for (Iterator<MyObj> i = getMyObjIterator(); i.hasNext(); ) {
  queue.put(i.next());
}
thread.interrupt();

但是,如果这样做,线程可能会在队列中仍有项目等待处理时中断。您可能需要考虑使用轮询而不是 ,这将允许处理线程在没有新输入的情况下等待一段时间时超时并终止。take


推荐