2012-05-11 83 views
3

Java在增加foreach循環時似乎掛起。我找不到任何人有類似的問題,所以也許我只是做錯了什麼,但我無法想象它是什麼。我從Neo4J數據庫中提取一組節點,然後遍歷它。在循環過程中,我不修改該組節點,但過了一段時間後,它會掛起。下面是做它的代碼:Java掛在foreach循環上

 IndexHits<Node> usrs = users.get("Type", "User"); 
     System.out.println("Operating on "+usrs.size()+" Users:"); 

     for (Node u : usrs) { 
      System.out.print("."); 
      if (inUserBlacklist(u)) 
       continue; 
      System.out.println("HA"); 
     } 

所有這一切inUserBlacklist(U)的作用是檢查節點u對預設的節點集,看是否節點是黑名單。它不會改變節點u的任何內容。

用戶是一個Neo4J索引,所以調用它的get()應該返回一個可迭代的IndexHits對象。這個foreach循環通過foreach循環遍歷269,938次。在該迭代結束時,它會打印「HA」,但不會打印另一個「。」。它只是在第269,939次迭代之前掛起。這使得它在foreach循環中被阻塞。總共應該有270,012次迭代。

我注意到我的黑名單包含74個項目,所有這些項目都應該在通過此循環時匹配一次。 270,012 - 74 = 269,938,但這並不能解釋爲什麼它被阻止。我所能想到的是,當我調用continue時,foreach循環正在遞增迭代器上的位置而不遞增其計數器。然後它到達集合的末尾,沒有更多,但櫃檯認爲它只在270,012中的269,938處。

你們中的任何一個人都知道爲什麼foreach循環會表現得像這樣?

編輯: 棧跟蹤顯示該進程確實停留在for循環(行116):

java.lang.Thread.State: RUNNABLE 
     at sun.nio.ch.FileDispatcher.pread0(Native Method) 
     at sun.nio.ch.FileDispatcher.pread(FileDispatcher.java:49) 
     at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:248) 
     at sun.nio.ch.IOUtil.read(IOUtil.java:224) 
     at sun.nio.ch.FileChannelImpl.read(FileChannelImpl.java:663) 
     at org.neo4j.kernel.impl.nioneo.store.PersistenceRow.readPosition(PersistenceRow.java:91) 
     at org.neo4j.kernel.impl.nioneo.store.PersistenceWindowPool.acquire(PersistenceWindowPool.java:177) 
     at org.neo4j.kernel.impl.nioneo.store.CommonAbstractStore.acquireWindow(CommonAbstractStore.java:559) 
     at org.neo4j.kernel.impl.nioneo.store.RelationshipStore.getChainRecord(RelationshipStore.java:349) 
     at org.neo4j.kernel.impl.nioneo.xa.ReadTransaction.getMoreRelationships(ReadTransaction.java:121) 
     at org.neo4j.kernel.impl.nioneo.xa.ReadTransaction.getMoreRelationships(ReadTransaction.java:104) 
     at org.neo4j.kernel.impl.persistence.PersistenceManager.getMoreRelationships(PersistenceManager.java:108) 
     at org.neo4j.kernel.impl.core.NodeManager.getMoreRelationships(NodeManager.java:666) 
     at org.neo4j.kernel.impl.core.NodeImpl.getMoreRelationships(NodeImpl.java:427) 
     - locked <0x77c9b4a0> (a org.neo4j.kernel.impl.core.NodeImpl) 
     at org.neo4j.kernel.impl.core.IntArrayIterator.fetchNextOrNull(IntArrayIterator.java:91) 
     at org.neo4j.kernel.impl.core.IntArrayIterator.fetchNextOrNull(IntArrayIterator.java:36) 
     at org.neo4j.helpers.collection.PrefetchingIterator.hasNext(PrefetchingIterator.java:55) 
     at org.neo4j.kernel.impl.traversal.TraversalBranchImpl.next(TraversalBranchImpl.java:128) 
     at org.neo4j.kernel.PreorderBreadthFirstSelector.next(PreorderBreadthFirstSelector.java:48) 
     at org.neo4j.kernel.impl.traversal.TraverserImpl$TraverserIterator.fetchNextOrNull(TraverserImpl.java:127) 
     at org.neo4j.kernel.impl.traversal.TraverserImpl$TraverserIterator.fetchNextOrNull(TraverserImpl.java:94) 
     at org.neo4j.helpers.collection.PrefetchingIterator.hasNext(PrefetchingIterator.java:55) 
     at org.neo4j.helpers.collection.IteratorWrapper.hasNext(IteratorWrapper.java:42) 
     at NodePlacement.LoadFromNode(NodePlacement.java:116) 

所以......它看起來像線程仍在運行,並且不會被阻止上的任何東西。但它並沒有脫離這部分代碼。也許關於我的數據庫的設置已經把它放到了一個無限循環?

+10

'inUserBlacklist'方法做了什麼?如果在「被阻塞」的時候進入調試器,堆棧跟蹤是什麼樣的? –

+0

您可能想要啓用GC日誌並查看Full GC是否正在減慢速度? – Chandra

+0

只是一個問題。你究竟如何分析結果。你會有這麼長的一系列.HA ......(我假設你編程了一些東西來計算確切的印刷品)。 74例你永遠不會打印醫管局,這可能是你的計數錯誤?有史以來最簡單的事情最難咬人! –

回答

0

掛起時,可以使用命令行中的Ctrl-Break或掛起執行(如果在調試器下運行),或使用jps和jstack工具獲取應用程序的線程轉儲並查看正在執行的方法。

在附註上,所有foreach循環都會從Iterable集合或數組中將Iterator實例撤回,並使用Iterator的hasNext()和next()方法。所以,如果這些方法中的任何一個會掛起,你會得到你現在看到的。

+0

在Unix系統上,使用'kill -3 JAVA_PID'轉儲所有線程堆棧跟蹤。 'jconsole'也可以幫助你通過GUI實現這一點。 –

+0

和/或VisualVM ... –

0

我打算出去走走,並建議問題出現在循環後面的代碼中。正如所寫的,代碼將打印「HA」,但除inUserBlacklist()之外的所有條目。如果您基於對「HA」輸出行的編程計數的假設,則您給出的計數表示代碼完成循環並去對其他事情,你沒有提供。

+0

爲了測試這個目的,我確保循環後唯一發生的事情是我在Neo4J事務中調用finish(),然後關閉Neo4J數據庫。程序在那之後終止。 – user1389906

+0

完成()調用可以掛起嗎?你可以在循環之後添加一個println來驗證你的代碼不會離開循環嗎? –

+0

我不確定finish()是否可以掛起。它是Neo4J庫的一部分。他們的文檔沒有提及finish()或shutdown()調用是否可以被阻塞。但是,我已經驗證代碼不會離開for循環。 – user1389906

0

嗯,我從來沒有想過究竟發生了什麼,但似乎在Neo4J數據庫的磁盤訪問中發生了問題。我回頭看了看創建它的方式,然後意識到我在創建數據庫的方式上犯了一個嚴重的錯誤。我重建了整個事情,現在我沒有這個問題。謝謝你們每一個人的幫助!