2016-07-26 52 views
0

我爲我的應用程序使用LinkedBlockingQueue進行隱式同步,但如果我使用queue.take()queue.poll(),前幾個元素在從隊列中獲取後不知何故丟失。我已經檢查過它是否是同一個對象。LinkedBlockingQueue第一個元素丟失

這裏是我的代碼:

for (QueryResult result : tmpPage) { 
    String objectId = result.getPropertyValueByQueryName("cmis:objectId"); 
    writer.writeFile(objectId); //Only for debugging reasons to 
           //compare the input and the output 
    try { 
     batchJobs.offer(new Node(objectId), 1,TimeUnit.HOURS); 
    } catch(Exception e) { 
     errorLogger.error(e.getMessage()); 
    } 
} 

,我採取或輪詢

Node node = null; 
while (!nodes.isEmpty()) { 
    while((node = nodes.take())!=null) { 
     writer.writeFile(node.getObjectID()); // Only for debugging reasons 
     if (node != null) { 
      //Do some stuff 
     } 
    } 
} 

曾有人遇到過類似的事情的地方嗎?

+2

你可以澄清「第一個從隊列中獲得它之後很少有元素會丟失「?你的意思是說,從隊列中移除元素後,它不再可用?順便說一下,'if(node!= null)'是不需要的。你在內部'while'循環的條件下保證'node!= null'。 – bradimus

回答

1

在隊列中,take()和poll()方法檢索數據並將其從隊列中移除。這可能是您丟失數據的原因。如果您想檢索數據但不想刪除它,請使用peek()。

+0

這是我計劃將它從隊列中取出,但似乎如果我在queue.poll()或queue.take()函數上使用多個線程,則會丟失一些元素。如果我想從隊列中取出某些東西,我是否必須設置鎖定?我認爲這個課程是線程安全的。 – Kaffi

+0

你能告訴我你使用這個方法的確切場景嗎?既然take()和pull()都是同步方法,但是兩個線程都可能在同一個對象上工作。所以數據將被彈出並由有機會,上下文切換到同一個線程和同一個線程再次調用poll(),你會在下一回閤中尋找線程2。 –

+0

親愛的Shailesh 你提到的那種情況實際上是問題所在。 – Kaffi

2

隊列是一個FIFO(先入先出)數據結構。一旦從隊列中取出一個對象,它將不再是該數據結構的一部分。你將不得不把它放回隊列中。

如果你只想看看元素,你會想使用一個peek()。

0

問題是莫迪先生提到的。

能否告訴我具體的使用方法?由於take()和pull()都是同步方法,但兩個線程都可能在同一個Object上工作,所以數據應該彈出並由兩個線程打印。有機會,上下文切換到同一個線程和相同的線程再次調用poll(),你會一直在尋找線程2在下一回合