1. 程式人生 > >wait/notify 實現多線程交叉備份

wait/notify 實現多線程交叉備份

== 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 實現多線程交叉備份