Titan是一个分布式图数据库,具体可参考官方文档中的介绍。
本文旨在验证Titan多线程事务隔离的实现。具体地说,Titan Instance会为每个线程开启一个transaction,使得各个线程之间的操作是独立的,这就使得多线程应用的开发特别简单,各种线程只需共用一个Titan Instance即可。这是官方文档的说明:http://s3.thinkaurelius.com/docs/titan/0.5.4/tx.html#_transaction_handling
下面做一个简单的验证:
用两个线程来操作一个titan instance(即一个TitanGraph对象),其中一个线程不执行commit操作,看另一个线程的commit操作是否会提交所有对titan instance的修改。
package test;
import com.thinkaurelius.titan.core.TitanFactory;
import com.thinkaurelius.titan.core.TitanGraph;
import com.thinkaurelius.titan.core.TitanVertex;
import com.tinkerpop.blueprints.Vertex;
public class ThreadIsolatedTest {
public static void main(String[] args) throws InterruptedException {
final TitanGraph g = TitanFactory.open("inmemory"); // 为测试方便,使用inmemory模式
Thread workerToCommit = new Thread(new Runnable() {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
TitanVertex v = g.addVertex();
System.out.println(threadName + " add vertex " + v.getId());
try {
System.out.println(threadName + " is going to sleep 0.5s");
Thread.sleep(500); // 等待另一个线程的操作完成
} catch (InterruptedException e) {
e.printStackTrace();
}
g.commit();
System.out.println(threadName + " committed");
}
});
Thread workerNotCommit = new Thread(new Runnable() {
@Override
public void run() {
String threadName = Thread.currentThread().getName();
TitanVertex v = g.addVertex();
System.out.println(threadName + " add vertex " + v.getId());
try {
System.out.println(threadName + " is going to sleep 1s");
Thread.sleep(1000); // 等待另一个线程的commit发生,看是否会提交本线程的操作
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(threadName + " finished");
}
});
workerNotCommit.start(); // 让不commit的线程先运行
workerToCommit.start();
workerNotCommit.join();
workerToCommit.join();
System.out.println("---------------- after committed --------------------");
Iterable<Vertex> vs = g.query().vertices();
System.out.println("committed vertex id:");
for (Vertex v : vs) {
System.out.println(v.getId());
}
g.shutdown();
}
}
程度的输出结果如下:
Thread-2 add vertex 256
Thread-2 is going to sleep 0.5s
Thread-3 add vertex 512
Thread-3 is going to sleep 1s
Thread-2 committed
Thread-3 finished
---------------- after committed --------------------
committed vertex id:
256
首先 Thread-2 添加了一个 id 为 256 的点,然后先不 commit,而是 sleep 0.5秒,等待另一个线程的操作。
于是 Thread-3 添加了一个 id 为 512 的点,然后不 commit,而是 sleep 1秒,确保在本线程退出前,Thread-2 已经执行了 commit 操作。
然后 Thread-2 commit,之后 Thread-3 退出。
最后检查一下图中有哪些点,发现只有 Thread-2 提交的 256.
这足以证明,每个线程对 Titan Instance 的操作都是相互隔离的。Titan Instance 对操作它的线程透明地实现了事务隔离,具体的实现方式可参见下一篇文章。另外,如果不想要线程隔离,而是希望各个线程都在一个事务里,可以用 TitanGraph 的 newTransaction 函数获得一个事务,然后各个线程共用一个 Transaction 对象来实现,具体可参见文档 http://s3.thinkaurelius.com/docs/titan/0.5.4/tx.html#multi-thread-tx