Java ArrayDeque不是';t为空,但poll方法返回null
我将此代码(模糊)作为大型应用程序的一部分,它在Java ArrayDeque不是';t为空,但poll方法返回null,java,queue,Java,Queue,我将此代码(模糊)作为大型应用程序的一部分,它在object.doSomething()行上得到一个NullPointerException。由于我们刚刚检查了isEmpty()调用,并且没有其他线程轮询此队列,这怎么可能呢?有其他线程添加到队列中;有没有可能把队列搞得一团糟 我试图阅读ArrayDeque的源代码,它使用head==tail检查isEmpty()。在添加过程中是否可能发生一些奇怪的碰撞尾部但是头部指向空 private final Queue<Task> activ
object.doSomething()
行上得到一个NullPointerException
。由于我们刚刚检查了isEmpty()
调用,并且没有其他线程轮询此队列,这怎么可能呢?有其他线程添加到队列中;有没有可能把队列搞得一团糟
我试图阅读ArrayDeque
的源代码,它使用head==tail
检查isEmpty()
。在添加过程中是否可能发生一些奇怪的碰撞尾部但是头部
指向空
private final Queue<Task> active = new ArrayDeque<Task>();
if (!this.active.isEmpty()) {
SomeType object = null;
object = this.active.poll();
object.doSomething();
}
private final Queue active=new ArrayDeque();
如果(!this.active.isEmpty()){
SomeType对象=null;
object=this.active.poll();
doSomething();
}
如中所述:
它们不是线程安全的在没有外部同步的情况下,它们不支持多线程并发访问
如合同所述:
它们不是线程安全的在没有外部同步的情况下,它们不支持多线程并发访问
即使没有其他线程轮询,也可能有其他线程在推送 这意味着在并发访问中,tail可能会被错误地修改,如果tail被损坏,您可能永远不会到达
head==tail
的点,因此出现NullPointerException
正如@dacwe所述,文档明确规定您(或此模糊应用程序的开发人员)不应在并发环境中使用ArrayDeque
,这是并发性可能存在的问题之一
它们不是线程安全的;在没有外部同步的情况下,它们不支持多线程并发访问
如果您想要线程安全,您可以使用;如果您需要线程安全,您可以使用
资源:
head==tail
的点,因此出现NullPointerException
正如@dacwe所述,文档明确规定您(或此模糊应用程序的开发人员)不应在并发环境中使用ArrayDeque
,这是并发性可能存在的问题之一
它们不是线程安全的;在没有外部同步的情况下,它们不支持多线程并发访问
如果您想要线程安全,您可以使用;如果您需要线程安全,您可以使用
资源:
active.isEmpty()
返回falseactive.addLast()
,以便active
已满并触发doubleCapacity()public E pollFirst() {
int h = head;
@SuppressWarnings("unchecked")
E result = (E) elements[h];
// Element is null if deque empty
if (result == null)
return null;
elements[h] = null; // Must null out slot
head = (h + 1) & (elements.length - 1);
return result;
}
public void addLast(E e) {
if (e == null)
throw new NullPointerException();
elements[tail] = e;
if ( (tail = (tail + 1) & (elements.length - 1)) == head)
doubleCapacity();
}
private void doubleCapacity() {
assert head == tail;
int p = head;
int n = elements.length;
int r = n - p; // number of elements to the right of p
int newCapacity = n << 1;
if (newCapacity < 0)
throw new IllegalStateException("Sorry, deque too big");
Object[] a = new Object[newCapacity];
System.arraycopy(elements, p, a, 0, r);
System.arraycopy(elements, 0, a, r, p);
elements = a;
head = 0;
tail = n;
}
public pollFirst(){
int h=头部;
@抑制警告(“未选中”)
E结果=(E)元素[h];
//如果deque为空,则元素为null
如果(结果==null)
返回null;
元素[h]=null;//必须将插槽中的元素设为null
头部=(h+1)和(元素长度-1);
返回结果;
}
公共无效地址(E){
如果(e==null)
抛出新的NullPointerException();
元素[尾]=e;
if((tail=(tail+1)和(elements.length-1))==头部)
双容量();
}
私人空间容量(){
断言头==尾;
INTP=头部;
int n=元素长度;
int r=n-p;//p右边的元素数
It NealStult= N您可以考虑当<代码> Active .Pull()/代码>访问在<代码> ArayDeQueLe.DouBeCopActhyId()/代码>中回收的旧元素[/d> >,DeQuy同时满。
一个可能的时间表:
轮询线程签出active.isEmpty()
返回false
轮询线程调用``active.pollFirst()来访问非原子元素[]
一个或多个其他线程以突发方式调用active.addLast()
,以便active
已满并触发doubleCapacity()
在doubleCapacity()中,元素[]被替换为新分配的数组,以便GC回收旧元素[]
轮询线程现在引用回收的元素[],可能会得到null
我猜你希望避免队列中的同步,而队列不是空的。为了避免由于DoubEcPaCuthy()引起的争用,确保队列被分配了足够大的容量,并且不会被调用AdultAdLADST[()被调用。但是,可能还有其他的种族需要考虑。