来自ArrayBlockingQueue
ArrayBlockingQueue的Javadoc:
添加
public boolean add(E e)
Inserts the specified element at the tail of this queue if it is possible to do so immediately without exceeding the queue's capacity, returning true upon success and throwing an IllegalStateException if this queue is full.
我总是将此声明(部分if it is possible to do so immediattely
)解释如下:
如果队列具有可用容量,则插入将成功。如果没有空的空间那么它就不会成功。
但我的理解在这里是错误的。
在一个简单的例子中,我决定使用ArrayBlockingQueue
作为例如20个元素(小队列)并且有一个线程正在执行:
queue.take()
尽管队列几乎为空,但另一个线程没有通过add
方法向队列添加元素。
我也通过调试验证了它。
一旦我将queue.add(element)
的调用替换为queue.put(element)
,该元素确实被添加到队列中。
那么这些方法有什么不同呢?
还有什么其他原因(除了能力之外)不会发生增加?
更新:
public class ConnectionListener implements Observer {
public static BlockingQueue<ConnectionObject> queueConnections = new ArrayBlockingQueue<ConnectionObject>(10);
@Override
public void update(Observable arg0, Object arg1) {
ConnectionObject con = ((ConnectionObject)arg1);
queueConnections.add(con);
}
}
ConnectionObject
只是String值的持有者。
public class ConnectionObject {
private String user;
private String ip;
//etc
}
消费者:
public class ConnectionTreeUpdater extends Thread {
@Override
public void run() {
while(true){
try {
final ConnectionObject con = ConnectionListener.queueConnections.take();
如果我使用add
,则不会抛出任何异常,但元素不会添加到队列中。
只是一个想法:也许是因为消费者在队列上“等待”,如果对于某些内部管理,该元素无法添加,则不会添加它,也不会抛出任何异常。可能就是这种情况。
否则我无法理解为什么没有异常并且put
代码有效。
put
和add
是否意味着使用不同的方式?
答案 0 :(得分:15)
真的很简单:
我认为上面的文档很清楚。如果您不同意,并希望获得第二意见,可以查看ArrayBlockingQueue
的源代码:
public boolean add(E e) {
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
}
public boolean offer(E e) {
if (e == null) throw new NullPointerException();
final ReentrantLock lock = this.lock;
lock.lock();
try {
if (count == items.length)
return false;
else {
insert(e);
return true;
}
} finally {
lock.unlock();
}
}
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
final E[] items = this.items;
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
try {
while (count == items.length)
notFull.await();
} catch (InterruptedException ie) {
notFull.signal(); // propagate to non-interrupted thread
throw ie;
}
insert(e);
} finally {
lock.unlock();
}
}
答案 1 :(得分:4)
调试问题的一个更重要的部分是编写测试用例以确保您认为正在发生的事情确实正在发生。这证明或反驳了你的理论。
下面的测试用例显示您使用的方法与文档(您引用的文档)完全相同:
public static void main(String[] args) {
final ArrayBlockingQueue<Integer> myQueue =
new ArrayBlockingQueue<Integer>(10);
Thread t1 = new Thread(new Runnable() {
public void run()
{
int i = 0;
while (true)
{
try
{
myQueue.add(i);
System.out.println("Added to queue! value: " +
i +
" size: " + myQueue.size());
i++;
}
catch (Exception e)
{
System.out.println("add() threw exception, size: " +
myQueue.size());
try
{
Thread.sleep(1000);
}
catch (InterruptedException ex)
{
Logger.getLogger(Main.class.getName()).log(Level.SEVERE,
null, ex);
}
}
}
}
});
Thread t2 = new Thread(new Runnable() {
public void run()
{
while (true)
{
try
{
Integer i = myQueue.take();
System.out.println("Took a off the queue! value: " +
i +
" size: " + myQueue.size());
Thread.sleep(100);
}
catch (InterruptedException ex)
{
Logger.getLogger(Main.class.getName()).log(Level.SEVERE,
null, ex);
}
}
}
});
t1.start();
t2.start();
}