Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/396.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java ArrayDeque不是';t为空,但poll方法返回null_Java_Queue - Fatal编程技术网

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
,这是并发性可能存在的问题之一


它们不是线程安全的;在没有外部同步的情况下,它们不支持多线程并发访问


如果您想要线程安全,您可以使用;如果您需要线程安全,您可以使用


资源:


即使没有其他线程轮询,也可能有其他线程在推送

这意味着在并发访问中,tail可能会被错误地修改,如果tail被损坏,您可能永远不会到达
head==tail
的点,因此出现
NullPointerException

正如@dacwe所述,文档明确规定您(或此模糊应用程序的开发人员)不应在并发环境中使用
ArrayDeque
,这是并发性可能存在的问题之一


它们不是线程安全的;在没有外部同步的情况下,它们不支持多线程并发访问


如果您想要线程安全,您可以使用;如果您需要线程安全,您可以使用


资源:


您可以考虑<代码> Active .Pull()/代码>访问在<代码> ArayDeQueLe.DouBeCopActhyAuthor(<代码>)中回收的旧元素[/d> >,DeQuy同时满。

一个可能的时间表:

  • 轮询线程签出
    active.isEmpty()
    返回false
  • 轮询线程调用``active.pollFirst()来访问非原子元素[]
  • 一个或多个其他线程以突发方式调用
    active.addLast()
    ,以便
    active
    已满并触发doubleCapacity()
  • 在doubleCapacity()中,元素[]被替换为新分配的数组,以便GC回收旧元素[]
  • 轮询线程现在引用回收的元素[],可能会得到null
  • 我的猜测是,您希望在队列不为空时避免轮询的同步。为了避免由于doubleCapacity()引起的争用,请确保为队列分配了足够大的容量,并且在调用addLast()时队列不会满。但是,根据实际的执行,可能需要考虑其他的种族。

    以下来自openJDK的源代码附在后面供参考

    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[()被调用。但是,可能还有其他的种族需要考虑。