3

增加 foreach 循环时,Java 似乎挂起。我找不到任何有类似问题的人,所以也许我只是做错了什么,但我无法想象它是什么。我正在从 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,以查看该节点是否属于黑名单的一部分。它不会改变关于节点 u 的任何内容。

Users 是一个 Neo4J 索引,因此对其调用 get() 应该返回一个可迭代的 IndexHits 对象。这个 foreach 循环运行了 269,938 次 foreach 循环。在该迭代结束时,它会打印“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)

所以......看起来线程仍在运行并且没有被任何东西阻塞。然而它并没有脱离这部分代码。也许关于我的数据库设置的某些东西使它陷入了无限循环?

4

3 回答 3

0

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

于 2012-05-11T18:18:01.657 回答
0

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

于 2012-05-15T17:52:52.653 回答
0

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

附带说明一下,所有 foreach 循环所做的都是Iterator从集合或数组中检索实例Iterable并使用 Iterator 的 hasNext() 和 next() 方法。所以,如果这些方法中的任何一个会挂起,你就会得到你现在看到的。

于 2012-05-11T17:17:10.150 回答