關於多執行緒處理資料併發問題處理
資料量多時需要要多執行緒處理,尤其在叢集環境下很可能發生資源競爭的情況,此時就需要謹慎的對資料加鎖,如果加鎖出了問題,也是個麻煩事。
為安全考慮,一般處理這種問題有幾個步驟:
為此個業務加開關,如果出現問題,將開關關閉。但是遇到一些緊急問題,開關關閉會影響業務,這時就需要走以下邏輯:
1、資料量多,則資料取出後用執行緒池分批處理資料。
2、資料量不多,單執行緒就可以處理;建議建一個執行緒表專門處理執行緒鎖問題。這裡我們建一個asgin_thread的執行緒表,表中的欄位有id,SYNSTATE,VERSION,其中SYNSTATE為同步狀態,VERSION為版本號;其中的id是自己定義的,加鎖時也只加鎖這個表中的某一條資料,不能對業務表進行加鎖,將事務放到biz層,這樣的話整個biz層的邏輯同在一個事務內,加鎖才起作用。此處用樂觀鎖處理,將asgin_thread的單條資料加鎖後,統一業務層的其他邏輯都完成事務提交後鎖釋放。以下是程式碼:
while (running) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
log.error("異常:", e);
}
List<Bean> tasklist = null;
try {
tasklist = asignThreadBiz.update(loadCount);
log.info("裝載已鎖定資料");
} catch (Exception e) {
log.error("執行緒出現鎖衝突,重新進行取資料....!",e);
continue;
}
if (tasklist != null && !tasklist.isEmpty()) {
WorkThread<List<Bean>> ecThread = createWorkThread();
ecThread.setTaskList(tasklist);
threadPool.execute(ecThread);
}
// 狀態重製
resetStatus();
}
處理資料流程:
asignDao.updateCount(); //執行緒表單條資料加鎖
List<Bean> retlist = new ArrayList<Bean>();
int retval = BeantDao.setLock(loadcount); //打標記
if(retval > 0){
retlist = beantDao.loadLock(); //取資料
}
樂觀鎖:
AsginThread asgin = this.load(100000L);
asgin.setSynstate(asgin.getSynstate()+1);
this.saveOrUpdate(asgin);