这个问题与我之前的一个问题有关..
在那里,阻塞性质被认为是一种优势。
我尝试开发一些简单的代码来演示阻塞性质,但我遇到了困难。我只是尝试制作一个大小为4的BlockingQueue
并尝试添加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();
}
}
我使用了这段代码。在这种情况下,我试图将5个元素放入大小为4的队列中。在这种情况下,应将4个元素(A,B,C,D)添加到队列中。然后我在打印时调用take()
方法。当我打电话给 System.out.println("1 = " + bq.take());
时,不应该自动将“E”插入队列吗?因为它有一个免费插槽?
答案 0 :(得分:11)
您是使用add
,offer
还是put
添加的?我假设您使用add
,因为它是唯一可以抛出IllegalStateException
的人;但如果您阅读table,您会看到如果您想要阻止语义,则应使用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();
}
现在put("E")
调用实际上会成功,因为它现在可以等到消费者线程从队列中删除“A”。最后一个take()
仍会无限制地阻塞,因为没有要移除的第六个元素。
答案 1 :(得分:2)
注意: put()在您的示例中将失败,因为put()将阻塞,直到空间可用。由于空间永远不可用,程序永远不会继续执行。
====旧答案======
一个BlockingQueue是一个接口,你必须使用其中一个实现类。
“阻止自然”只是声明你可以从你的队列中请求一些东西,如果它是空的,它所在的线程将阻止(等待)直到某些东西被添加到队列中然后继续处理。
ArrayBlockingQueue
DelayQueue
LinkedBlockingQueue
PriorityBlockingQueue
SynchronousQueue
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();
}
//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();
}
答案 2 :(得分:1)
专门回答你的问题:Offer是一个非阻塞商品调用,所以在你发布的一个单线程方法中,对商品的调用('E')只返回false而不修改完整队列。如果您使用了阻塞放('E')调用,它将一直睡眠,直到空间可用。永远在你的简单例子中。您需要从队列中读取一个单独的线程,以便为put完成创建空间。
答案 3 :(得分:0)
您好了解更多信息
/**
* 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;