2016-11-10 205 views
0

我想根據一個found here建立自己的BlockingQueue變體。從零開始實施BlockingQueue的問題

public class ThreadSafeContainer<E> { 
private Node front; 
private Node end; 
private int capacity; 
private int size; 

public ThreadSafeContainer(int capacity) { 
    size = 0; 
    this.capacity = capacity; 
} 

public synchronized void add(E item) { 
    while (size == capacity) { 
     try { 
      wait(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    if (size == 0) { 
     notifyAll(); 
    } 

    Node tmp = new Node(item); 

    if (end == null) { 
     front = tmp; 
     end = tmp; 
    } else { 
     end.next = tmp; 
     end = end.next; 
    } 

    size++; 
} 

public synchronized E remove() { 
    while (size == 0) { 
     try { 
      wait(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    if (size == capacity) { 
     notifyAll(); 
    } 

    E item = front.item; 
    front = front.next; 
    size--; 
    return item; 
} 

private class Node { 
    E item; 
    Node next; 

    public Node(E item) { 
     this.item = item; 
    } 
} 

但由於某些原因,當我試圖像這樣

Thread thread1 = new Thread() { 
     public void run() { 
      queue.add(1); 
      queue.add(2); 
     } 
    }; 

    Thread thread2 = new Thread() { 
     public void run() { 
      System.out.println(queue.remove()); 
      System.out.println(queue.remove()); 
     } 
    };  

我得到這個例外

異常的線程 「主題-3」 顯示java.lang.NullPointerException 運行的線程ThreadSafeContainer.remove(ThreadSafeContainer.java:52) at ThreadPractice $ 2.run(ThreadPractice.java:17) at java.lang.Thread.run(Unknown Source)

我可以通過將大小== 0更改爲前== ==刪除錯誤,但它仍然不會輸出相同。

+0

可能重複[什麼是NullPointerException,以及如何解決它?](http://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-doi-i-fix -it) – bradimus

+0

@bradimus在功能上,我的代碼應該具有相同的行爲,除了使用我自己設計的預先存在的列表結構。大小++/- 應該反映我使用的示例的效果。然而他的運行良好,而我的錯誤。 – generaltsao

回答

0

目前,如果remove()的呼叫曾經刪除最後一個元素,那麼最終的結果是front == null,但最終結果爲end == //the last created node。這意味着下一次撥打add將只更新end,而不是front,相應的撥打remove()會拋出您的NPE。

您可以檢查front == nullremove()結束,或更改end == nulladd的測試size == 0front == null。另外,如果您發佈堆棧跟蹤,添加註釋可以指示您的代碼段中的哪一行與異常中的行號相對應。