阻止队列 - 需要更多信息

Cha*_*ara 5 java queue concurrency data-structures

这个问题与我之前的一个问题有关..

上一篇文章

在那里,提到阻塞性质是一个优点.

我尝试开发一些简单的代码来演示阻塞性,但是我遇到了困难.我只是尝试制作一个BlockingQueue4号尺寸并尝试添加5个元素并最终得到了一个java.lang.IllegalStateException.有人能给我看一个阻止性质的代码示例BlockingQueue吗?


public static void main(String[] args) {
    BlockingQueue<String> bq = new LinkedBlockingQueue<String>(4);

    try {
        bq.offer("A");
        bq.offer("B");
        bq.offer("C");
        bq.offer("D");
        bq.offer("E");

        System.out.println("1 = " + bq.take());
        System.out.println("2 = " + bq.take());
        System.out.println("3 = " + bq.take());
        System.out.println("4 = " + bq.take());
        System.out.println("5 = " + bq.take());
        System.out.println("6 = " + bq.take());
    } catch (Exception e) {
        // TODO: handle exception
        e.printStackTrace();
    }
}
Run Code Online (Sandbox Code Playgroud)

我使用了这段代码.在这种情况下,我试图将5个元素放入大小为4的队列中.在这种情况下,应将4个元素(A,B,C,D)添加到队列中.然后我take()在打印时调用方法.我打电话时不应该自动将"E"插入队列System.out.println("1 = " + bq.take());吗?因为它有一个免费插槽?

Mic*_*ers 11

是你与添加add,offerput?我假设你正在使用add,因为它是唯一可以投掷的人IllegalStateException; 但如果您阅读该,您将看到如果您想要阻止语义,您应该使用put(并take删除).

编辑:您的示例有几个问题.

首先,我将回答"我take()第一次打电话时为什么不插入E ?"的问题.答案是,当你打电话时take(),你已经尝试过并且未能插入E.一旦空间被释放,就没有任何东西可以插入.

现在,如果你改变offer()put(),put("E")将永远不会回来.为什么?因为它正在等待其他一些线程从队列中删除一个元素.请记住,BlockingQueues是专为多线程访问而设计的.如果您有单线程应用程序,阻塞是无用的(实际上比无用的更糟).

这是一个改进的例子:

public static void main(String[] args) {
    final BlockingQueue<String> bq = new LinkedBlockingQueue<String>(4);

    Runnable producer = new Runnable() {
        public void run() {
            try {
                bq.put("A");
                bq.put("B");
                bq.put("C");
                bq.put("D");
                bq.put("E");
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt(); 
            }
        }
    };
    Runnable consumer = new Runnable() {
        public void run() {
            try {
                System.out.println("1 = " + bq.take());
                System.out.println("2 = " + bq.take());
                System.out.println("3 = " + bq.take());
                System.out.println("4 = " + bq.take());
                System.out.println("5 = " + bq.take());
                System.out.println("6 = " + bq.take());
            } catch (InterruptedException ex) {
                Thread.currentThread().interrupt();
            }
        }
    };
    new Thread(producer).start();
    new Thread(consumer).start();
}
Run Code Online (Sandbox Code Playgroud)

现在put("E")调用实际上会成功,因为它现在可以等到消费者线程从队列中删除"A".最后一个take()仍然会无限制地阻塞,因为没有第六个要删除的元素.

  • Put没有超时; 如果您需要超时,请使用优惠. (2认同)