为什么iterator.hasNext不能与BlockingQueue一起使用?

Var*_*rde 6 java collections multithreading java.util.concurrent

我试图在BlockingQueue上使用迭代器方法并发现hasNext()是非阻塞的 - 即它不会等到添加更多元素,而是在没有元素时返回false.

所以这里是问题:

  1. 这是糟糕的设计还是错误的期望?
  2. 有没有办法使用BLockingQueue的阻塞方法及其父类Collection方法(例如,如果某些方法需要一个集合,我可以传递一个阻塞队列,并希望它的处理将等到Queue有更多元素)

这是一个示例代码块

public class SomeContainer{
     public static void main(String[] args){
        BlockingQueue bq = new LinkedBlockingQueue();
        SomeContainer h = new SomeContainer();
        Producer p = new Producer(bq);
        Consumer c = new Consumer(bq);
        p.produce();
        c.consume();
    }

    static class Producer{
        BlockingQueue q;
        public Producer(BlockingQueue q) {
            this.q = q;
        }

        void produce(){
        new Thread(){
            public void run() {
            for(int i=0; i<10; i++){
                for(int j=0;j<10; j++){
                    q.add(i+" - "+j);
                }
                try {
                    Thread.sleep(30000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            };
        }.start();
        }
    }


    static class Consumer{
         BlockingQueue q;

         public Consumer(BlockingQueue q) {
             this.q = q;
         }

        void consume() {
            new Thread() {
                public void run() {
                    Iterator itr = q.iterator();
                    while (itr.hasNext())
                        System.out.println(itr.next());
                }
            }.start();
        }
        }
    }
Run Code Online (Sandbox Code Playgroud)

此代码仅打印最多一次迭代.

Sea*_*oyd 10

只是不要将迭代器与队列一起使用.使用peek()poll()替代或take()如果它是BlockingQueue:

void consume() {
    new Thread() {
        @Override
        public void run() {
            Object value;
            // actually, when using a BlockingQueue,
            // take() would be better than poll()
            while ((value=q.poll())!=null)
                System.out.println(value);
        }
    }.start();
}
Run Code Online (Sandbox Code Playgroud)

A QueueIterable因为它是a Collection并因此需要提供一种iterator()方法,但不应该使用它,或者你不应该首先使用Queue.


Joh*_*erg 3

1)这是糟糕的设计,还是错误的期望?

错误的期望,因为否则它会违反迭代器的契约,该契约上Iterator.next()说:Throws: NoSuchElementException - iteration has no more elements. 如果next()会阻塞,则永远不会抛出异常。

2)有没有办法使用阻塞方法

是的,例如通过扩展类并重写nexthasNext方法来改为使用阻塞例程。请注意,在这种情况下hasNext需要始终返回true- 这再次违反了合同。