Java挂在foreach循环上

时间:2012-05-11 17:11:59

标签: java foreach neo4j blocking

Java在增加foreach循环时似乎挂了。我找不到有类似问题的人,所以也许我只是做错了什么,但我无法想象它是什么。我从Neo4J数据库中取出一组节点,然后迭代它。我不会在循环期间修改那组节点,但过了一会儿,它就会挂起。以下是执行此操作的代码:

        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,以查看节点是否属于黑名单。它不会改变任何有关Node 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)

所以......看起来线程仍然在运行而且没有阻塞任何东西。然而,它并没有脱离这部分代码。也许有关我的数据库设置的事情已经把它变成了无限循环?

3 个答案:

答案 0 :(得分:0)

当它挂起时,您可以在命令行中使用Ctrl-Break,或者如果在调试器下运行则暂停执行,或者使用jps和jstack工具获取应用程序的线程转储并查看正在执行的方法。

在旁注中,所有foreach循环都会从Iterator集合或数组中撤消Iterable实例,并使用Iterator的hasNext()和next()方法。所以,如果这些方法中的任何一个都会挂起,那么你现在就能看到你所看到的。

答案 1 :(得分:0)

我要走出困境并建议问题是在循环后的代码中。如上所述,除了inUserBlacklist()的条目之外,代码将打印“HA”。如果您的假设基于“HA”输出行的编程计数,那么您给出的计数表示代码已完成循环,继续你没有提供的其他东西。

答案 2 :(得分:0)

好吧,我从来没有弄清楚到底发生了什么,但似乎问题出现在Neo4J数据库的磁盘访问中。我回去看看我创建它的方式,我意识到我在创建数据库的方式上犯了一个严重的错误。我重建了整件事,现在我没有问题。谢谢大家的帮助!