Search code examples
androidexceptionqueuenosuchelementexception

Android's Queue poll() call throws NoSuchElementException


I have a queue implementation. To perform a de-queue I use the poll() API to remove the head, but it throws the NoSuchElementException which it shouldn't. Can anyone explain me why this happens? My queue has more than enough data to be de-queued.

protected boolean enQueue(ByteBuffer data){
    if (queue.offer(data)){
        return true;
    }else {
        return false;
    }   
}

protected ByteBuffer deQueue(){
    ByteBuffer data = null;
    try{
        if(getQueueCount() > 0)
        {
            data = queue.poll();
            if(data != null){
                return data;
            }else {
                return null;
            }
        }
        else{
            return null;
        }
    }
    catch(NoSuchElementException e){
        e.printStackTrace();
        return null;
    }
}

EDIT:

java.util.Queue<ByteBuffer> queue;

public Queue(){
    queue = new LinkedList<ByteBuffer>();
}
protected int getQueueCount(){
    return queue.size();
}

StackTrace:

03-04 14:58:50.205: W/System.err(7937): java.util.NoSuchElementException 03-04 14:58:50.205: W/System.err(7937): at java.util.LinkedList.removeFirstImpl(LinkedList.java:689) 03-04 14:58:50.205: W/System.err(7937): at java.util.LinkedList.removeFirst(LinkedList.java:676) 03-04 14:58:50.205: W/System.err(7937): at java.util.LinkedList.poll(LinkedList.java:895) 03-04 14:58:50.205: W/System.err(7937): at com.android.testapp.Queue.deQueue(Queue.java:37) 03-04 14:58:50.205: W/System.err(7937): at com.android.testapp.DisplayData.run(LogViewActivity.java:1164)

EDIT 2:

ENQUEUE

Queue.getInstance().enQueue(tempByteBufRead);

This I use to enqueue the data received through Bluetooth in bluetooth.class. tempByteBufRead is a Bytebuffer. And this is done in a separate thread.

DEQUEUE

while( Queue.getInstance().getQueueCount() <= 0);


        try {
            if(LLTestAppActivity.DEBUG){
                Log.d("DisplayData", "Crossed queue count...");
            }
            ByteBuffer tempByteBuf = Queue.getInstance().deQueue(); 
            if(null == tempByteBuf){
                Log.d("DisplayData", "No data in queue...");
            }
            else{
                   //TODO:
                 }
            }catch(){}

This is how I dequeue. This is in different class file. And this is another thread used to display data onto a text view.


Solution

  • Your queue is empty (or rather, missing its first element). The poll method in LinkedList is implemented as such:

    public E poll() {
        if (size==0)
            return null;
        return removeFirst();
    }
    

    and removeFirst is a method that does throw NoSuchElementException.

    You should try and figure out what causes the first element to go missing, since apparently your queue reports a non-zero number of elements. How do you push objects onto the queue?

    EDIT: Suggested changes to your code after seeing your edits:

    // use a thread-safe queue implementation:
    java.util.concurrent.BlockingQueue<ByteBuffer> queue;
    
    // make the constructor private, since it's a singleton you don't want anyone else to be able to instantiate
    private Queue() {
        queue = new LinkedBlockingQueue<ByteBuffer>();
    }
    
    // enQueue and deQueue without a bunch of redundant code:
    protected boolean enQueue(ByteBuffer data) {
        return queue.offer(data);
    }
    
    protected ByteBuffer deQueue() {
        return queue.take();
    }
    
    // enqueue data like this:
    Queue.getInstance().enQueue(tempByteBufRead);
    
    // and dequeue it:
    try {
        ByteBuffer tempButeBuf = Queue.getInstance().deQueue();
        // TODO: do something useful with the buffer
    } catch (InterruptedException e) {
    }