简体   繁体   English

阻止队列 - 需要更多信息

[英]Blocking Queue - Need more information

This question is related with one of my earlier questions.. 这个问题与我之前的一个问题有关..

Previous Post 上一篇文章

In there the blocking nature is mentioned as an advantage. 在那里,提到阻塞性质是一个优点。

I tried to develop some simple code to demonstrate the blocking nature but I got stuck. 我尝试开发一些简单的代码来演示阻塞性质,但我遇到了困难。 I just tried to make a BlockingQueue of size 4 and tried to add 5 elements and ended up with a java.lang.IllegalStateException . 我只是尝试制作一个大小为4的BlockingQueue并试图添加5个元素,最后得到一个java.lang.IllegalStateException Can someone show me a code example for blocking nature of BlockingQueue ? 有人能给我看一个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();
    }
}

I used this code segment. 我使用了这段代码。 In this case I am trying to put 5 elements to a queue with size 4. In this case 4 elements (A,B,C,D) should be added to queue. 在这种情况下,我试图将5个元素放入大小为4的队列中。在这种情况下,应将4个元素(A,B,C,D)添加到队列中。 Then I am calling take() method while printing. 然后我在打印时调用take()方法。 Shouldn't "E" be inserted automatically to the queue when I call System.out.println("1 = " + bq.take()); 当我调用System.out.println("1 = " + bq.take());不应该将“E”自动插入队列System.out.println("1 = " + bq.take()); ? Because it gets one free slot? 因为它有一个免费插槽?

Were you adding with add , offer , or put ? 您是否添加了addofferput I assume you were using add , since it is the only one that can throw an IllegalStateException ; 我假设你使用add ,因为它是唯一一个可以抛出IllegalStateException ; but if you read the table , you'll see that if you want blocking semantics, you should be using put (and take to remove). 但如果你看了 ,你会发现,如果你想阻塞语义,你应该使用put (并take删除)。

Edit: There are a couple of problems with your example. 编辑:您的示例有几个问题。

First I'll answer the question "Why doesn't E get inserted when I call take() the first time?" 首先,我将回答这个问题“当我第一次打电话给take()时为什么不插入E?” The answer is that by the time you call take() , you have already tried and failed to insert E. There is then nothing to insert once the space has been freed. 答案是,当你调用take() ,你已经尝试过并且未能插入E.一旦空间被释放,就没有任何东西可以插入。

Now if you changed offer() to put() , put("E") will never return. 现在,如果您将offer()更改offer() put() ,则put("E")将永远不会返回。 Why? 为什么? Because it's waiting for some other thread to remove an element from the queue. 因为它正在等待其他一些线程从队列中删除一个元素。 Remember, BlockingQueues are designed for multiple threads to access. 请记住, BlockingQueues是为多个线程设计的。 Blocking is useless (actually worse than useless) if you have a single-threaded application. 如果您有单线程应用程序,阻塞是无用的(实际上比无用的更糟)。

Here is an improved example: 这是一个改进的例子:

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();
}

Now the put("E") call will actually succeed, since it can now wait until the consumer thread removes "A" from the queue. 现在put("E")调用实际上会成功,因为它现在可以等到消费者线程从队列中删除“A”。 The last take() will still block infinitely, since there is no sixth element to remove. 最后一个take()仍将无限阻塞,因为没有要删除的第六个元素。

mmyers beat me to it :P (+1) mmyers打败了我:P(+1)
that should be what you need, good luck! 那应该是你需要的,祝你好运!

NOTE: put() will fail in your example because put() will block until space is available. 注意: put()将在您的示例中失败,因为put()将阻塞,直到空间可用。 Since space is never available, the program never continues execution. 由于空间永远不可用,程序永远不会继续执行。

==== old answer====== ====旧答案======

a BlockingQueue is an interface, you'll have to use one of the implementating classes. 一个BlockingQueue是一个接口,你必须使用其中一个实现类。

The "Blocking Nature" simply states that you can request something from your queue, and if it is empty, the thread it is in will block (wait) until something gets added to the queue and then continue processing. “阻止自然”只是声明你可以从你的队列中请求一些东西,如果它是空的,它所在的线程将阻塞 (等待),直到某些东西被添加到队列然后继续处理。

ArrayBlockingQueue
DelayQueue
LinkedBlockingQueue
PriorityBlockingQueue
SynchronousQueue

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html

 //your main collection LinkedBlockingQueue<Integer> lbq = new LinkedBlockingQueue<Integer>(); //Add your values lbq.put(100); lbq.put(200); //take() will actually remove the first value from the collection, //or block if no value exists yet. //you will either have to interrupt the blocking, //or insert something into the queue for the program execution to continue int currVal = 0; try { currVal = lbq.take(); } catch (InterruptedException e) { e.printStackTrace(); } 

To specifically answer your question: Offer is a nonblocking offer call, so in a single threaded method like the one you posted, the call to offer('E') simply returns false without modifying the full queue. 要专门回答你的问题:Offer是一个非阻塞商品调用,所以在你发布的一个单线程方法中,对商品的调用('E')只返回false而不修改完整队列。 If you used the blocking put('E') call, it would sleep until space became available. 如果您使用了阻塞放('E')调用,它将一直睡眠,直到空间可用。 Forever in your simple example. 永远在你的简单例子中。 You would need to have a separate thread reading off of the queue to create space for the put to complete. 您需要从队列中读取一个单独的线程,以便为put完成创建空间。

Hi more info this class 您好更多信息这个课程

 /**
 * Inserts the specified element into this queue if it is possible to do
 * so immediately without violating capacity restrictions, returning
 * {@code true} upon success and throwing an
 * {@code IllegalStateException} if no space is currently available.
 * When using a capacity-restricted queue, it is generally preferable to
 * use {@link #offer(Object) offer}.
 *
 * @param e the element to add
 * @return {@code true} (as specified by {@link Collection#add})
 * @throws IllegalStateException if the element cannot be added at this
 *         time due to capacity restrictions
 * @throws ClassCastException if the class of the specified element
 *         prevents it from being added to this queue
 * @throws NullPointerException if the specified element is null
 * @throws IllegalArgumentException if some property of the specified
 *         element prevents it from being added to this queue
 */
boolean add(E e);

/**
 * Inserts the specified element into this queue if it is possible to do
 * so immediately without violating capacity restrictions, returning
 * {@code true} upon success and {@code false} if no space is currently
 * available.  When using a capacity-restricted queue, this method is
 * generally preferable to {@link #add}, which can fail to insert an
 * element only by throwing an exception.
 *
 * @param e the element to add
 * @return {@code true} if the element was added to this queue, else
 *         {@code false}
 * @throws ClassCastException if the class of the specified element
 *         prevents it from being added to this queue
 * @throws NullPointerException if the specified element is null
 * @throws IllegalArgumentException if some property of the specified
 *         element prevents it from being added to this queue
 */
boolean offer(E e);

/**
 * Inserts the specified element into this queue, waiting if necessary
 * for space to become available.
 *
 * @param e the element to add
 * @throws InterruptedException if interrupted while waiting
 * @throws ClassCastException if the class of the specified element
 *         prevents it from being added to this queue
 * @throws NullPointerException if the specified element is null
 * @throws IllegalArgumentException if some property of the specified
 *         element prevents it from being added to this queue
 */
void put(E e) throws InterruptedException;

/**
 * Inserts the specified element into this queue, waiting up to the
 * specified wait time if necessary for space to become available.
 *
 * @param e the element to add
 * @param timeout how long to wait before giving up, in units of
 *        {@code unit}
 * @param unit a {@code TimeUnit} determining how to interpret the
 *        {@code timeout} parameter
 * @return {@code true} if successful, or {@code false} if
 *         the specified waiting time elapses before space is available
 * @throws InterruptedException if interrupted while waiting
 * @throws ClassCastException if the class of the specified element
 *         prevents it from being added to this queue
 * @throws NullPointerException if the specified element is null
 * @throws IllegalArgumentException if some property of the specified
 *         element prevents it from being added to this queue
 */
boolean offer(E e, long timeout, TimeUnit unit)
    throws InterruptedException;

/**
 * Retrieves and removes the head of this queue, waiting if necessary
 * until an element becomes available.
 *
 * @return the head of this queue
 * @throws InterruptedException if interrupted while waiting
 */
E take() throws InterruptedException;

/**
 * Retrieves and removes the head of this queue, waiting up to the
 * specified wait time if necessary for an element to become available.
 *
 * @param timeout how long to wait before giving up, in units of
 *        {@code unit}
 * @param unit a {@code TimeUnit} determining how to interpret the
 *        {@code timeout} parameter
 * @return the head of this queue, or {@code null} if the
 *         specified waiting time elapses before an element is available
 * @throws InterruptedException if interrupted while waiting
 */
E poll(long timeout, TimeUnit unit)
    throws InterruptedException;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM