Java 基于嵌入式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

我需要一个带有ObjectDB的原子计数器,但下面的代码不能像我预期的那样工作:

    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);