java中多線程中測試某個條件的變化用 if 還是用 while?


    最近在研究wait和notify方法,發現有個地方要注意,但是網上又說得不是很明白的地方,就是經典的生產者和消費模式,使用wait和notify實現,判斷list是否為空的這個為什么要用while而不能使用if呢?其實是因為當線程wait之后,又被喚醒的時候,是從wait后面開始執行,而不是又從頭開始執行的,所以如果用if的話,被喚醒之后就不會在判斷if中的條件,而是繼續往下執行了,如果list只是添加了一個數據,而存在兩個消費者被喚醒的話,就會出現溢出的問題了,因為不會在判斷size是否==0就直接執行remove了。但是如果使用while的話,從wait下面繼續執行,還會返回執行while的條件判斷,size>0了才會執行remove操作,所以這個必須使用while,而不能使用if來作為判斷。

    以下代碼是一個簡單的實踐,參考: http://www.cnblogs.com/hapjin/p/5492645.html(做了適當的調整)
      Add類,負責添加數據:
    
public class Add {
    private String lock;
    public Add(String lock) {
        super();
        this.lock = lock;
    }
    public void add() {
        synchronized (lock) {
            ValueObject.list.add("anyString");
            lock.notifyAll();
        }
    }
}
public class ThreadAdd extends Thread {
    private Add p;
    public ThreadAdd(Add p) {
        super();
        this.p = p;
    }
    @Override
    public void run() {
        p.add();
    }
}

  

 
     Subtract類,負責刪除數據
public class Subtract {
    private String lock;
    public Subtract(String lock) {
        super();
        this.lock = lock;
    }
    public boolean check() {
        System.out.println("check");
        return true;
    }
    public void subtract() {
        try {
            synchronized (lock) {
                if(check() && ValueObject.list.size() == 0) {//將這里的if改成while即可保證不出現越界異常!!!!
                    System.out.println("wait begin ThreadName="
                            + Thread.currentThread().getName());
                    lock.wait();
                    System.out.println("wait   end ThreadName="
                            + Thread.currentThread().getName());
                }
                ValueObject.list.remove(0);
                System.out.println("list size=" + ValueObject.list.size());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class ThreadSubtract extends Thread {
    private Subtract r;
    public ThreadSubtract(Subtract r) {
        super();
        this.r = r;
    }
    @Override
    public void run() {
        r.subtract();
    }
}

  

 
     封裝的List隊列:
public class ValueObject {
    public static List list = new ArrayList();
}

 

 
     測試類:
public class Run {
    public static void main(String[] args) throws InterruptedException {
        String lock = new String("");
        Add add = new Add(lock);
        Subtract subtract = new Subtract(lock);
        ThreadSubtract subtract1Thread = new ThreadSubtract(subtract);
        subtract1Thread.setName("subtract1Thread");
        subtract1Thread.start();
        ThreadSubtract subtract2Thread = new ThreadSubtract(subtract);
        subtract2Thread.setName("subtract2Thread");
        subtract2Thread.start();
        Thread.sleep(1000);
        ThreadAdd addThread = new ThreadAdd(add);
        addThread.setName("addThread");
        addThread.start();
    }
}

 

 






免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM