wait/notify 實現多線程交叉備份
阿新 • • 發佈:2017-09-12
== ted pre start 解決 syn tac col des
一、任務
創建20個線程,其中10個線程是將數據備份到 A 數據庫中,另外10 個線程將數據備份到 B 數據庫中,並且備份 A 數據庫和 備份 B 數據庫的是交叉運行的。
二、實現
1、實現備份 A 數據庫和備份 B 數據庫的 task。
/** * Description: 當flag=true的時候備份 A 數據庫 * 當flag=false的時候備份 B數據庫 以此實現交叉備份 */ public class TaskBackup { volatile private boolean flag=false;// 采用volatile關鍵字,使變量於多個線程之間可見synchronized public void backupA(){ //synchronized 關鍵字,避免多個線程對同一對象的修改,導致“臟讀” try { //記住,這裏的判斷一定要用while 而不是用if,為什麽呢?因為存在多個線程,不止備份B數據庫的線程在等待,可能備份A數據庫的線程也在等待,如果用if //可能會導致 同類喚醒同類的 情況導致線程的“假死”。 while (flag==false){this.wait(); } System.out.println(Thread.currentThread().getName()+"正在備份 A 數據庫!");//模擬備份數據庫 flag=false; this.notifyAll();//喚醒所有等待的線程,當然這裏並不會喚醒backupA 的線程,原因在於,backupA的線程這個時候又做了一個while判斷,導致線程繼續在等待了,而只有backupB的線程被喚醒了 } catch (InterruptedException e) { e.printStackTrace(); } }synchronized public void backupB(){ try { while (flag==true){ this.wait(); } System.out.println(Thread.currentThread().getName()+"正在備份 B 數據庫!");//模擬備份數據庫
flag=true; this.notifyAll(); } catch (InterruptedException e) { e.printStackTrace(); } } }
2、分別創建線程執行 備份任務
public class ThreadBackupA extends Thread { private TaskBackup taskPackup; public ThreadBackupA(TaskBackup taskPackup) { this.taskPackup = taskPackup; } @Override public void run() { super.run(); taskPackup.backupA(); } }
public class ThreadBackupB extends Thread { private TaskBackup taskPackup; public ThreadBackupB(TaskBackup taskPackup) { this.taskPackup = taskPackup; } @Override public void run() { super.run(); taskPackup.backupB(); } }
3、執行任務查看結果
public class Run { public static void main(String[] args) { TaskBackup taskPackup=new TaskBackup(); for (int i=0;i<20;i++){ ThreadBackupA threadBackupA=new ThreadBackupA(taskPackup); ThreadBackupB threadBackupB=new ThreadBackupB(taskPackup); threadBackupA.start(); threadBackupB.start(); } } }
三、結語
覺得這個例子寫得特別棒,所以特地記錄了一下。它把 諸如 線程notify過程中 wait條件發生改變、同類喚醒同類導致的“假死”問題 等,都做了一個很好的概括應用和解決。筆主資歷尚淺,說的不好的地方,還請不吝指教,謝謝!
wait/notify 實現多線程交叉備份