2016-01-20 81 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. 返回遞增的個案號碼。

其他線程將等到事務提交。