2016-01-20 47 views
1

我测试了在我的hibernate调用中同时运行两个任务。它不正确地创建两个具有相同大小写的对象。我想锁定此方法,直到object1获取其案例号,然后object2将获得不同的案例号。锁定Java任务

public String getNextCaseNumberFromDatabase(String tenantId) { 

     LOGGER.entering(getClass().getName(), "getNextCaseNumber"); 

      Configuration caseNumberStartValueConfiguration = null; 
     List<Case> cases = null; 

     try { 
      caseNumberStartValueConfiguration = configurationService.getConfigurationByKey(ConfigurationKey.CASE_NUMBER_START_VALUE, tenantId); 
     } catch (RuntimeException ex) { 
      throw ex; 
     } 

     try { 
      cases = caseService.getAllCases(tenantId); 
     } catch (RuntimeException ex) { 
      throw ex; 
     } 

     //LOCK DATABASE HERE 
     synchronized(this) { 
      // Get the largest case number in the database and increment from it 
      int largestCaseNumber = 0; 
      for (int i = 0; i < cases.size(); i++) { 
       if (cases.get(i).getCaseNumber() != null) { 
        if (Integer.parseInt(cases.get(i).getCaseNumber()) > largestCaseNumber) { 
         largestCaseNumber = Integer.parseInt(cases.get(i).getCaseNumber()); 
        } 
       } 
      } 

      // Set the case number to either the next largest number or the configured value, whichever is larger 
      String caseNumber = "1"; 
      if (largestCaseNumber >= Integer.parseInt(caseNumberStartValueConfiguration.getConfigurationValue())) { 
       caseNumber = Integer.toString(largestCaseNumber + 1); 
      } else if (caseNumberStartValueConfiguration != null) { 
       caseNumber = caseNumberStartValueConfiguration.getConfigurationValue(); 
      } 


      LOGGER.exiting(getClass().getName(), "getNextCaseNumber"); 
      return caseNumber; 
     }//END LOCK HERE 

    } 

正如你可以看到我添加了同步(这){} 它什么都不做。任何想法,我需要做不同的正确锁定这个?我是否需要锁定整个方法?

+0

'这'在两个线程中是不同的,所以同步没有做任何事情。蛮力的方法是同步整个方法。或者,你可以有一个静态成员对象(在CaseHelper中)并在该对象上同步(而不是'this')。 –

+0

@MarkTucker我试图使方法“公共同步字符串getNextCaseNumberFromDatabase(字符串tenantId)”,但它仍然给重复的数字。有任何想法吗? – Jay266

回答

1

做同步这样

public synchronized String getNextCaseNumberFromDatabase(String tenantId) { 

} 

是一样的做同步这样

public String getNextCaseNumberFromDatabase(String tenantId) { 
    syncronized(this) { 

    }  
} 

两种情况使用this来syncronize。正如@MarkTucker建议的那样,'这'在两个线程中是不同的,所以同步并没有做任何事情。你需要一个静态字段就可以了

private static Object sync = new Object(); 

    public String getNextCaseNumberFromDatabase(String tenantId) { 
     syncronized(sync) { 

     }  
    } 

同步,但它是不是最好的方法。尝试在数据库中仅使用一行作为最大案例编号,并在事务中获取下一个案例编号。

  1. 打开一个事务。

  2. 获取当前悲观锁定案件编号(LockMode.PESSIMISTIC_WRITE或类似的,它依赖于Hibernate的 版)

    session.get(CaseNumber.class, caseNumberId, LockMode.PESSIMISTIC_WRITE)

  3. 递增的情况下,数量和更新CaseNumber

  4. 提交交易。

  5. 返回递增的个案号码。

其他线程将等到事务提交。