notifyAll notify順序

今天看到一篇問題,提問線程喚醒順序。

具體代碼如下:

 import java.util.LinkedList;
import java.util.List;

public class ThreadRunSort {

    /** 
     * 對象鎖 
     */  
    private final Object object = new Object();  
    private List<Integer> sleep = new LinkedList<>();
    private List<Integer> notify = new LinkedList<>();
    /** 
     * 該線程作爲一個喚醒線程 
     */  
    public void startThread(int i) {  
        Thread t = new Thread(new Runnable() {  
            @Override  
            public void run() {  
                synchronized (object) {  
                    try {
                        System.out.println(Thread.currentThread().getName()+"進入休眠");
                        sleep.add(i);
                        object.wait();
                        System.out.println(Thread.currentThread().getName()+"線程已經喚醒");
                        notify.add(i);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }  
            }  
        });  
        t.setName("Thread"+i);
        t.start();  
    }  

    public static void main(String[] args) {  
        ThreadRunSort a = new ThreadRunSort();
        for(int i =1;i<22;i++){
            a.startThread(i);
        }

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println();
        for(int i =1;i<22;i++){
            synchronized (a.object) {
                a.object.notify();
            }
        }

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("休眠順序"+a.sleep);
        System.out.println("喚醒順序"+a.notify);


    }    
}

發現,輸入的順序是不定的,比如:

休眠順序[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
喚醒順序[1, 5, 4, 3, 2, 7, 6, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 21]

 

 

但是,當修改了其中notify代碼:

for(int i =1;i<22;i++){
            try {
                Thread.sleep(10);  // 在這裏sleep確保notify會順序執行
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            synchronized (a.object) {
                a.object.notify();
            }
        }

 

順序就變成

休眠順序[1, 3, 4, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
喚醒順序[1, 3, 4, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]

 

可以理解在wait時候,放入的是一個FIFO的隊列?每次notify其實就是出隊的形式。(上面順序有問題是因爲線程按順序出隊後,搶佔鎖的順序和CPU有關)

 

但是,把代碼改成notifyAll後:

休眠順序[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
喚醒順序[21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

變成了stack出棧的形式。。

具體的問題還要再研究下。。。。

 

原問題傳送門:https://ask.csdn.net/questions/387308#answer_972330

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章