根据调用线程,相同 vertex/query 抛出和不抛出 NPE

Same vertex/query throws and does NOT throw a NPE depending on calling thread

这是"Transaction was rolled back more times than it was started" Exception?

的延续

我设法缩小了自从我开始使用 OrientGraphFactory 以来遇到的一些问题(意思是在我使用 OrientGraph 之前并没有看到这个 NPE)

package oThread;

import java.io.File;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.impls.orient.OrientGraph;
import com.tinkerpop.blueprints.impls.orient.OrientGraphFactory;

public class OThread {
    public static void main(String[] args){
        File f = new File(System.getProperty("user.home"), "oThread");
        f.mkdir();          
        OrientGraphFactory factory = new OrientGraphFactory("plocal:" + System.getProperty("user.home") + File.separatorChar + "oThread").setupPool(1, 10);
        factory.setAutoStartTx(false);
        final Vertex v1;
        final OrientGraph g = factory.getTx();
        g.begin();
        v1 = g.addVertex(null);
        g.commit();
        Thread t = new Thread(new Runnable(){
            public void run(){
                try{
                    v1.query().direction(Direction.OUT).labels("currentSuite").has("ID", 0).edges().iterator().hasNext();
                }
                catch(Exception x){
                    x.toString();
                }
            }
        });
        t.start();
        try {
             v1.query().direction(Direction.OUT).labels("currentSuite").has("ID", 0).edges().iterator().hasNext();
            t.join();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

线程内的查询抛出 NPE,而线程外的查询则没有。

堆栈跟踪是

java.lang.NullPointerException
    at com.tinkerpop.blueprints.impls.orient.OrientBaseGraph.getEdgeClassNames(OrientBaseGraph.java:307)
    at com.tinkerpop.blueprints.impls.orient.OrientVertex.getEdges(OrientVertex.java:1005)
    at com.tinkerpop.blueprints.impls.orient.OrientVertex.getEdges(OrientVertex.java:988)
    at com.tinkerpop.blueprints.util.DefaultVertexQuery$DefaultVertexQueryIterable.<init>(DefaultVertexQuery.java:110)
    at com.tinkerpop.blueprints.util.DefaultVertexQuery.edges(DefaultVertexQuery.java:80)
    at oThread.OThread.run(OThread.java:28)
    at java.lang.Thread.run(Thread.java:745)

jvm 1.7.0_79 orientdb 2.0.12 CE。 OS X 10.9

有线索吗?非常感谢!

更新:

似乎通过向工厂询问另一个Graph实例并检索在查询之前创建的顶点不会失败。我可以使用它。

问题:

"What happens when multiple clients add edges on the same vertex? OrientDB could throw the OConcurrentModificationException exception as well" 如果一个线程删除了一条边而另一个线程添加了第二条边,这个说法是否成立?

出于好奇。

这里的问题是您在两个不同的线程中使用同一个数据库实例,您应该避免这种情况,因为数据库不是线程安全的。

OConcurrentModificationException 当您从两个不同的进程更新同一个顶点时可能会发生。这是一个技术细节:如果一个顶点有少于 40 条边(这是一个可配置的阈值),则边指针存储在顶点文档中,因此添加一条边也会导致顶点版本的增加。超过此阈值的边存储在外部结构(SBTreeBonsai)中,因此添加边不会导致顶点版本增加;在这种情况下,您没有 OConcurrentModificationException。 只需确保获取两个不同的顶点实例并且不要从两个线程在同一个对象上并发工作,这可能会导致问题。