Java 基于嵌入式ObjectDB的多线程处理
我需要一个带有ObjectDB的原子计数器,但下面的代码不能像我预期的那样工作:Java 基于嵌入式ObjectDB的多线程处理,java,multithreading,jpa,objectdb,Java,Multithreading,Jpa,Objectdb,我需要一个带有ObjectDB的原子计数器,但下面的代码不能像我预期的那样工作: final EntityManagerFactory emf = Persistence.createEntityManagerFactory("test.odb"); EntityManager em = emf.createEntityManager(); Point p = new Point(0, 0); em.getTransaction().begin(); em
final EntityManagerFactory emf = Persistence.createEntityManagerFactory("test.odb");
EntityManager em = emf.createEntityManager();
Point p = new Point(0, 0);
em.getTransaction().begin();
em.persist(p);
em.getTransaction().commit();
em.close();
final CountDownLatch l = new CountDownLatch(100);
for (int i = 0; i < 100; i++) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
//Query q = em.createQuery("UPDATE Point SET x = x + 1");
Query query = em.createQuery("UPDATE Point SET x = x + 1");
query.executeUpdate();
em.getTransaction().commit();
em.close();
l.countDown();
}
});
t.start();
}
l.await();
em = emf.createEntityManager();
TypedQuery<Point> myquery = em.createQuery("SELECT p from Point p", Point.class);
List<Point> results = myquery.getResultList();
System.out.println("X coordiate is: " + results.get(0).getX());
em.close();
它应该打印出X坐标为100。但事实上,事实并非如此
我的代码有什么问题?您可以通过以下方法之一修复代码: 同步您的更新查询,以便它们将依次执行,而不是同时执行:
synchronized (lock) {
em.createQuery("UPDATE Point SET x = x + 1").executeUpdate();
}
锁定对象必须是所有线程共享的一个对象
或者,通过设置悲观锁定超时来使用ObjectDB/JPA锁定,例如:
Map<String, Integer> properties =
Collections.singletonMap("javax.persistence.lock.timeout", 1000);
EntityManagerFactory emf =
Persistence.createEntityManagerFactory(
"objectdb:$objectdb/db/test.tmp;drop", properties);
最好为Point创建一个DAO类,并包装persist、merge。。。改为使用同步函数的函数 或者,带有getAndIncrement的AtomicInteger应该可以解决您的问题,而不需要同步和锁定
Point point = em.find(Point.class, 1, LockModeType.PESSIMISTIC_WRITE);
point.setX(point.getX() + 1);