如何讓 10 個線程按照順序打印 0123456789

如何讓 10 個線程按照順序打印 0123456789?

  1. 設定一個 orderNum,每個線程執行結束之後,更新 orderNum,指明下一個要執行的線程。並且喚醒所有的等待線程。

  2. 在每一個線程的開始,要 while 判斷 orderNum 是否等於自己的要求值!!不是,則 wait,是則執行本線程。

                                     while(順序不匹配){
                                          wait
                                      }
                                         update orderNum 

import java.util.ArrayList;
import java.util.List;
public class thredSortedPrint {
    public static void main(String[] args) {
        //創建10個線程
        List<myThread> list = new ArrayList<myThread>();
        for(int i=10;i>0;i--){
            myThread thread = new myThread(i);
            thread.start();
        }
    }
    //創建一個內部靜態類
    static class myThread extends Thread{
        public int Num;
        static int orderNum = 1;
        //創建一個靜態的object類作爲共同的互斥鎖資源
        static final Object object = new Object();
        public myThread (int num){
            this.Num = num;
        };
        @Override
        public void run(){
            synchronized (object){
                //順序不匹配則等待,並讓出鎖資源
                while(Num != orderNum){
                    try {
                        System.out.println(Thread.currentThread().getName()+":wait");
                        //鎖是object,用object.wait(),當前線程被阻塞,進入等待隊列,同時釋放互斥鎖object
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //匹配則輸出打印,更新orderNum,並通知所有線程。
                System.out.println(Thread.currentThread().getName()+":"+Num);
                orderNum++;
                //通知互斥鎖的等待隊列
                object.notifyAll();
            }
        }
    }
}

運行並查看結果,如下。

Thread-0:wait
Thread-1:wait
Thread-3:wait
Thread-4:wait
Thread-7:wait
Thread-8:wait
Thread-2:wait
Thread-6:wait
Thread-5:wait
Thread-9:1
Thread-5:wait
Thread-6:wait
Thread-2:wait
Thread-8:2
Thread-7:3
Thread-4:wait
Thread-3:wait
Thread-1:wait
Thread-0:wait
Thread-2:wait
Thread-6:4
Thread-5:5
Thread-2:wait
Thread-0:wait
Thread-1:wait
Thread-3:wait
Thread-4:6
Thread-3:7
Thread-1:wait
Thread-0:wait
Thread-2:8
Thread-0:wait
Thread-1:9
Thread-0:10

補充:如果通知等待隊列的語句改成  object.notify(),可能會導致所有等待的線程都處於等待狀態,應該被喚醒的線程沒有機會再被喚醒。如下,啓動的線程爭搶CPU資源,如果打印順序剛好匹配,則執行並隨機通知一個處於等待隊列的線程。但是若所有線程都啓動了,除去已執行完的線程,剩下的都在隊列裏,這時候Thread-8執行完後隨機通知,被通知到恰好是Thread-3,而此時應該被通知的是Thread-7。Thread-3因打印順序不匹配,進入等待隊列。這時候剩餘所有線程都在隊列裏,也就沒有線程會被通知並執行了,形成了活鎖。

//通知互斥鎖的等待隊列
   object.notify();

 

Thread-2:wait
Thread-3:wait
Thread-7:wait
Thread-6:wait
Thread-1:wait
Thread-5:wait
Thread-9:1
Thread-2:wait
Thread-0:wait
Thread-4:wait
Thread-8:2
Thread-3:wait

 

運用jconsole工具查看線程執行情況 : https://blog.csdn.net/Henry_Lin_Wind/article/details/103408654 

剩餘的線程全部在等待,但是並沒有死鎖,所以要慎重使用notify()。

那什麼時候可以使用 notify() 呢?需要滿足以下三個條件:
1. 所有等待線程擁有相同的等待條件;
2. 所有等待線程被喚醒後,執行相同的操作;
3. 只需要喚醒一個線程。
 

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