多線程併發學習(四):線程中sleep,wait,notify,,notifyAll,join,yield等常用方法辨析

1. sleep()方法

使線程暫時休眠。線程的調度執行是按照優先級的高低順序進行的,當高級線程未完成即未死亡時,低級線程沒有機會獲得處理器。有時候優先級高的線程需要優先級低的線程來配合它,或者優先級高的線程需要完成一些費時的操作,此時優先級高的線程應該讓出處理器,使優先級低的線程有機會執行。爲了達到這個目的,可以再run()方法中調用sleep()方法使自己放棄處理器資源,休眠一段時間。

參考API文檔,sleep方法是一個靜態方法,休眠時間長短由該方法的參數決定。
public static native void sleep(long millis) throws InterruptedException

 sleep(long)使當前線程進入停滯狀態,所以執行sleep()的線程在指定的時間內肯定不會被執行; 
 sleep(long)可使優先級低的線程得到執行的機會,當然也可以讓同優先級和高優先級的線程有執行的機會; 
 sleep(long)是不會釋放鎖標誌的

使當前執行線程休眠(臨時停止執行)指定的毫秒數。 線程並不失去對任何監視程序的所有權。

參數: millis - 用毫秒爲單位的睡眠時間。

拋出: InterruptedException

public class InterruptTest {
    public static void main(String[] args){
       MyThread thread = new MyThread();
       thread.start();
       try{
           Thread.sleep(10000);//主線程調用sleep方法,主線程休眠
       }catch (InterruptedException e){}
       thread.interrupt();//在thread休眠時,調用該方法時將其打斷。打斷後,thread會拋出異常,該子線程結束
    }
}
class MyThread extends Thread{
    boolean flag = true;
    public void run(){
       while(flag){
           System.out.println("=="+new Date()+"==");
           try{ //在此處必須使用try-catch,由於sleep已經拋出異常,此處也必須處理異常。但                是並不能寫成 public void run() throws InterruptedException。因爲run方法爲重寫方法,重寫方法不能拋出和被重寫方法不同的異常。
              sleep(1000);//每隔1秒鐘打印一次系統時間
           }catch (InterruptedException e){
              return; 
           }
       }
    }
}

2. wait()方法和notify()、notifyAll() 

wait()方法的作用:讓該線程處於等待狀態。

notify()方法的作用:喚醒處於wait的線程。

notifyAll()方法的作用:喚醒所有處於wait狀態的線程。

 這三個方法用於協調多個線程對共享數據的存取,所以必須在Synchronized語句塊內使用這三個方法。Synchronized這個關鍵字用於保護共享數據,阻止其他線程對共享數據的存取。但是這樣程序的流程就很不靈活了,如何才能在當前線程還沒退出Synchronized數據塊時讓其他線程也有機會訪問共享數據呢?此時就用這三個方法來靈活控制。 
wait()方法使當前線程暫停執行並釋放對象鎖標誌,讓其他線程可以進入Synchronized數據塊,當前線程被放入對象等待池中。當調用 notify()方法後,將從對象的等待池中移走一個任意的線程並放到鎖標誌等待池中,只有鎖標誌等待池中的線程能夠獲取鎖標誌;如果鎖標誌等待池中沒有線程,則notify()不起作用。 
notifyAll()則從對象等待池中移走所有等待那個對象的線程並放到鎖標誌等待池中。 
注意 這三個方法都是java.lang.Ojbect的方法! 

3. run()和start()

把需要並行處理的代碼放在run()方法中,start()方法啓動線程將自動調用 run()方法,這是由Java的內存機制規定的。並且run()方法必須是public訪問權限,返回值類型爲void

4. join()方法

她是合併某個線程的方法。把一個線程合併到正在執行的線程當中。合併後,當前線程等待合進來的線程先執行完成後繼續執行。

實例:測試現象爲合併後子線程先執行,結束後主線程開始執行

public class JoinTest {
    public static void main(String[] args) {
       NewThread t = new NewThread("t thread"); //[1]創建一個名爲“t thread”的子線程
       t.start();
       try { //[2]join和sleep一樣,也拋出異常,所以同樣的處理方法
           t.join();//[3]把子線程合併到主線程中來,此刻先執行子線程後執行主線程
       }catch (InterruptedException e) {} 
       for(int i=1;i<=5;i++){
           System.out.println("This is main thread");
        }
    }   
}
class NewThread extends Thread {
    NewThread(String s) { //[4]給線程命名的方法,具體參考API文檔。
       super(s);
    }
    public void run() {
       for(int i = 1;i<=5;i++) {
           System.out.println("This is "+getName());
           try {
              sleep(1000);
           }catch (InterruptedException e) {
              return;
           }
       }
    }
}

5. yield()方法

她是一種讓出CPU,給其他線程執行的方法。

實例:定義兩個子線程,每當滿足條件時,讓出線程給對方執行

public class YieldTest {
    public static void main(String[] args){
       NewThread1 t1 = new NewThread1("t1");
       NewThread1 t2 = new NewThread1("t2");
       t1.start(); 
       t2.start();
    }
}
class NewThread1 extends Thread{
    NewThread1(Strings){
       super(s);
    }
    public void run() {
       for(int i=1;i<=100;i++){
       System.out.println(getName()+":"+i);
       if(i==0){
           yield();
        }
       }
    }
}

 

參考:https://blog.csdn.net/tongxuexie/article/details/80145663

           https://blog.csdn.net/tongxuexie/article/details/80175330

 

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