java.util.HashMap / Neo4j多线程永远挂起

时间:2015-11-18 11:50:51

标签: java multithreading neo4j

$ java -version
java version "1.7.0_65"
Java(TM) SE Runtime Environment (build 1.7.0_65-b17)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)

Neo4j版本= 2.2.6

两个线程试图访问同一毫秒内的同一个节点,并迭代大约500多个关系。结果是两个线程都永远挂起。

可能有什么修复方法或正确方法? (除此之外,"不要做两次。")

更新

使用JStack获取线程转储,看起来它与neo4j无关,但与HashSet / HashMap有关。请参阅下面的更新....

日志输出 - 记下线程序列1& 2:

17:12:12.798 (neo4j-ro-pool-2) DEBUG [db.neo4j.Neo4jDao] - Open neo4j tx
17:12:12.798 (neo4j-ro-pool-2) DEBUG [db.neo4j.Neo4jDao] - Getting Node for [XYZ]
17:12:12.798 (neo4j-ro-pool-1) DEBUG [db.neo4j.Neo4jDao] - Open neo4j tx
17:12:12.798 (neo4j-ro-pool-1) DEBUG [db.neo4j.Neo4jDao] - Getting Node for [XYZ]
17:12:12.800 (neo4j-ro-pool-2) DEBUG [db.neo4j.Neo4jDao] - Got Node[284172852]
17:12:12.800 (neo4j-ro-pool-2) DEBUG [db.neo4j.Neo4jDao] - Getting Relationships for Node[284172852]
17:12:12.800 (neo4j-ro-pool-1) DEBUG [db.neo4j.Neo4jDao] - Got Node[284172852]
17:12:12.800 (neo4j-ro-pool-1) DEBUG [db.neo4j.Neo4jDao] - Getting Relationships for Node[284172852]

Neo4jDao内的代码:

public Data addNamesToData(Data data) {
    LOG.debug("Open neo4j tx");
    try (Transaction tx = graphdb.beginTx()) {
        LOG.debug("Getting Node for [{}]", data);
        Node node = getNode(data);
        LOG.debug("Got {}", node);
        if (node == null) {
            LOG.debug("Existing Node for [{}] NOT FOUND", data);
            tx.success();
            return data;
        }
        addNames(node, data);
        tx.success();
        return data;
    } finally {
        LOG.debug("Close neo4j tx");
    }
}
private Data addNames(Node node, Data data) {
    LOG.debug("Getting Relationships for {}", node);
    Iterable<Relationship> rels = node.getRelationships(RelType.HAS_NAME_DATA, Direction.OUTGOING);
    int count = 0;
    for (Relationship rel : rels) { // Approx 500+ Relationships
        String name = NodeUtils.getNameFromNode(rel.getEndNode());
        LOG.trace("Adding Name [{}] to Data [{}]", name, data );
        data.addName(name);
        count++;
    }
    LOG.debug("Got {} Relationships for [{}]", count, node);
    return data;
}

Data.addName():

private final Set<String> nameSet = new HashSet<>();

public void addName(String name) {
    if(name != null) {
        this.nameSet.add(name);
    }
}

更新

使用JStack获取线程转储,看起来它与neo4j无关,但与HashSet / HashMap有关。

注意: Data的实例在每个帖子上都不同....

"neo4j-ro-pool-2" prio=10 tid=0x00007f572c002000 nid=0x6ebf runnable [0x00007f4eb40d8000]
   java.lang.Thread.State: RUNNABLE
        at java.util.HashMap.put(HashMap.java:494)
        at java.util.HashSet.add(HashSet.java:217)
        at data.Data.addName(Data.java:162)
        at db.neo4j.Neo4jDao.addNames(Neo4jDao.java:231)
        at db.neo4j.Neo4jDao.addNamesToData(Neo4jDao.java:216)
        at bus.subscriber.NamesSubscriber.handle(NamesSubscriber.java:39)
        at bus.subscriber.NamesSubscriber.handle(NamesSubscriber.java:18)
        at bus.adaptor.SubscriberAdaptor$Task.run(SubscriberAdaptor.java:102)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
        - <0x00007f5845c439d8> (a java.util.concurrent.ThreadPoolExecutor$Worker)

"neo4j-ro-pool-1" prio=10 tid=0x00007f572c001000 nid=0x6ebe runnable [0x00007f4eb3cd4000]
   java.lang.Thread.State: RUNNABLE
        at java.util.HashMap.put(HashMap.java:494)
        at java.util.HashSet.add(HashSet.java:217)
        at data.Data.addName(Data.java:162)
        at db.neo4j.Neo4jDao.addNames(Neo4jDao.java:231)
        at db.neo4j.Neo4jDao.addNamesToData(Neo4jDao.java:216)
        at bus.subscriber.NamesSubscriber.handle(NamesSubscriber.java:39)
        at bus.subscriber.NamesSubscriber.handle(NamesSubscriber.java:18)
        at bus.adaptor.SubscriberAdaptor$Task.run(SubscriberAdaptor.java:102)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
        - <0x00007f58494161d8> (a java.util.concurrent.ThreadPoolExecutor$Worker)

使用this blog中的提示我已经确定哪个线程正在咀嚼CPU。

$ top -n1 -H | grep -m1 java
28350 ubuntu    20   0 95.143g 0.013t 2.383g R 99.9 45.7   1154:16 java
$ printf "%x\n" 28350
6ebe

从线程转储中我们看到nid=0x6ebe是线程"neo4j-ro-pool-1"。不确定这有什么帮助。

0 个答案:

没有答案