1. 程式人生 > >五、執行緒狀態管理

五、執行緒狀態管理

1、執行緒睡眠—sleep:     執行緒睡眠的原因:執行緒執行的太快,或需要強制執行到下一個執行緒。    執行緒睡眠的方法(兩個):       sleep(long millis)在指定的毫秒數內讓正在執行的執行緒休眠。       sleep(long millis,int nanos)在指定的毫秒數加指定的納秒數內讓正在執行的執行緒休眠。

執行緒睡眠的程式碼演示:

public class SynTest {
    public static void main(String[] args) {
        new Thread(new CountDown(),"倒計時").start();
    }
}

class CountDown implements Runnable{
    int time = 10;
    public void run() {
        while (true) {
            if(time>=0){
                System.out.println(Thread.currentThread().getName() + ":" + time--);
                try {
                    Thread.sleep(1000);                                                    //睡眠時間為1秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

每隔一秒則會列印一次,列印結果為:

倒計時:10
倒計時:9
倒計時:8
倒計時:7
倒計時:6
倒計時:5
倒計時:4
倒計時:3
倒計時:2
倒計時:1
倒計時:0

      擴充套件:Java執行緒排程是Java多執行緒的核心,只有良好的排程,才能充分發揮系統的效能,提高程式的執行效率。但是不管程式設計師怎麼編寫排程,只能最大限度的影響執行緒執行的次序,而不能做到精準控制。因為使用sleep方法之後,執行緒是進入阻塞狀態的,只有當睡眠的時間結束,才會重新進入到就緒狀態,而就緒狀態進入到執行狀態,是由系統控制的,我們不可能精準的去幹涉它,所以如果呼叫Thread.sleep(1000)使得執行緒睡眠1秒,可能結果會大於1秒。

2、執行緒讓步—yield:   該方法和sleep方法類似,也是Thread類提供的一個靜態方法,可以讓正在執行的執行緒暫停,但是不會進入阻塞狀態,而是直接進入就緒狀態。相當於只是將當前執行緒暫停一下,然後重新進入就緒的執行緒池中,讓執行緒排程器重新排程一次。也會出現某個執行緒呼叫yield方法後暫停,但之後排程器又將其排程出來重新進入到執行狀態。

public class SynTest {
    public static void main(String[] args) {
        yieldDemo ms = new yieldDemo();
        Thread t1 = new Thread(ms,"張三吃完還剩");
        Thread t2 = new Thread(ms,"李四吃完還剩");
        Thread t3 = new Thread(ms,"王五吃完還剩");
        t1.start();
        t2.start();
        t3.start();
    }
}
class yieldDemo implements Runnable{
    int count = 20;
    public void run() {
        while (true) {
                if(count>0){
                    System.out.println(Thread.currentThread().getName() + count-- + "個瓜");
                    if(count % 2 == 0){
                        Thread.yield();                  //執行緒讓步
                    }
            }
        }
    }
}

sleep和yield的區別:

      ①、sleep方法宣告丟擲InterruptedException,呼叫該方法需要捕獲該異常。yield沒有宣告異常,也無需捕獲。       ②、sleep方法暫停當前執行緒後,會進入阻塞狀態,只有當睡眠時間到了,才會轉入就緒狀態。而yield方法呼叫後 ,是直接進入就緒狀態。

3、執行緒合併—join:

      當B執行緒執行到了A執行緒的.join()方法時,B執行緒就會等待,等A執行緒都執行完畢,B執行緒才會執行。       join可以用來臨時加入執行緒執行。以下為程式碼演示:

public static void main(String[] args) throws InterruptedException {    
        yieldDemo ms = new yieldDemo();
        Thread t1 = new Thread(ms,"張三吃完還剩");
        Thread t2 = new Thread(ms,"李四吃完還剩");
        Thread t3 = new Thread(ms,"王五吃完還剩");
        t1.start();
        t1.join();
        
        t2.start();
        t3.start();
        System.out.println( "主執行緒");
    }

4、停止執行緒:

      原stop方法因有缺陷已經停用了,那麼現在改如何停止執行緒?現在分享一種,就是讓run方法結束。       開啟多執行緒執行,執行的程式碼通常是迴圈結構,只要控制住迴圈,就可以讓run方法結束,也就是執行緒結束。

具體程式碼如下:

 1 public class StopThread {
 2 
 3     public static void main(String[] args) {
 4         int num = 0;
 5         StopTh st = new StopTh();
 6         Thread t1 = new Thread(st);
 7         Thread t2 = new Thread(st);
 8         t1.start();
 9         t2.start();
10         //設定主執行緒執行50次,執行結束之後停止執行緒
11         while (true) {
12             if(num++ == 50){                        
13                 st.flagChange();
14                 break;
15             }
16             System.out.println(Thread.currentThread().getName() + "..." + num);
17         }
18     }
19 }
20 
21 class StopTh implements Runnable{
22 
23     private boolean flag = true;
24     public void run() {
25         while(flag){
26             System.out.println(Thread.currentThread().getName() + "stop run" );
27         }
28     }
29     public void flagChange(){
30         flag = false;
31     }
32 }

特殊情況:當執行緒處於了凍結狀態,就不會讀取到標記,也就不會結束。當沒有指定方法讓凍結的執行緒回覆到執行狀態時,我們需要對凍結狀態進行清除,也就是強制讓執行緒恢復到執行狀態中來,這樣可就可以操作標記讓執行緒結束。   Thread類提供該方法: interrupt();(如果執行緒在呼叫Object類的wait()、wait(long)、wait(long,int)方法,或者該類的join()、join(long)、join(long、int)、sleep(long)或sleep(long、int)方法過程中受阻,則其中斷狀態將被清除,還將收到一個InterruptedException。) 5、設定優先順序:

      每個執行緒執行時都有一個優先順序的屬性,優先順序高的執行緒可以獲得較多的執行機會,而優先順序低的執行緒則獲得較少的執行機會。與執行緒休眠類似,執行緒的優先順序仍然無法保障執行緒的執行次序。只不過,優先順序高的執行緒獲取CPU資源的概率較大,優先順序低的也並非沒機會執行。   Thread類中提供了優先順序的三個常量,程式碼如下:

MAX_PRIORITY   =10

MIN_PRIORITY   =1

NORM_PRIORITY   =5
-----------------------------------------------------
 ThreadDemo td = new ThreadDemo();
 Thread t1 = new Thread(td,"張三");
 t1.priority(9);            //設定優先順序
 t1.start();              //設定完畢