From Gossip@Openhome

Java Gossip: 執行緒生命周期

執行緒的四個主要週期狀態如下所示:
執行緒生命週期

當您實例化一個Thread物件並執行start()之後,執行緒進入Runnable狀態並開始執行run()方法。

雖然執行緒看起來像是同時執行,但事實上同一時間點上,還是只有一個執行緒在動作,只是執行緒之間切換的動作很快,所以看來像是同時執行。

執行緒有其優先權,由1(Thread.MIN_PRIORITY)到10(Thread.MAX_PRIORITY)預設是 Thread.NORM_PRIORITY(5),您可以使用Thread的setPriority()方法來設定執行緒的優先權,設定必須在1到10之間,否則會丟出IllegalArgumentException

優先權高的執行緒會先被執行完畢,然後才會輪到優先權低的執行緒,如果優先權相同,則輸流執行(Round-robin方式)

決大多數的作業系統都支援timeslicing,簡單的說就是作業 系統會為每個執行緒分配一小段CPU時間(quantum),時間一到就換下一個執行緒,即使現有的執行緒還沒結束。對於不支援timeslicing的 作業系統,每一個執行緒必須完成後,才能輪到下一個執行緒,在這樣的作業系統中,如果您想要讓目前執行緒禮讓一下其它執行緒,讓它們有機會取得執行權,您 可以在呼叫緒行緒的yield()方法,例如:
public class SomeClass {
    // .....
        Thread thread = new Thread(new Runnable() {
            public void run() {
                // ....
                while(true) {
                    // ....
                    Thread.yield();  // 暫時讓出執行權
                }
            }
        });
        thread.start();
    // ....
}

yield()方法讓同樣優先權的執行緒有被執行的機會,當執行緒執行yield()方法讓出執行權時,它會再度加入執行緒的 排班,等待再度取得執行權,對於支援timeslicing的作業系統,呼叫yield()是不太需要的,因為作業系統會自動分配時間給執行緒輪流執行。

有幾種狀況會讓執行緒進入Not Runnable狀態(或是blocked狀態)
  1. 呼叫sleep()
  2. 呼叫wait()
  3. 等待I/O完成

當執行緒在Not Runnable狀態時,執行緒是可以被執行的,但有某些原因阻止它執行(例如等待使用者的輸入),執行緒排班器將不分配執行時間給這個執行緒,直到以下 的幾個情況讓執行緒回到Runnable狀態:
  1. 執行緒呼叫notify()
  2. 執行緒呼叫notifyAll()
  3. 執行緒呼叫interrupt()

當執行緒因為I/O而進入blocked狀態,它必須等到I/O完成才可以離開這個狀態。

最後,如果執行的工作完成(或發生例外)而離開run()方法,則執行緒執行完畢,進入Dead狀態,您可以使用isAlive()方法來測試執行緒是否 存活。

如果您查詢Java的線上API文件,您會發現有suspend()、resume()、stop()等方法,這些方法Java並不建議您使用,而且已經 被標示為"deprecated",這些方法建議您在需要的時候自行實作。

這邊舉個簡單的例子,當您使用Thread.sleep()讓執行緒暫停執行進入Not Runnable狀態,您可以使用interrupt()讓它離開Not Runnable狀態,當使用sleep()暫時進入Not Runnable狀態而您interrupt()時,會丟出InterruptedException例外物件,例如:

  • InterruptDemo.java 
package onlyfun.caterpillar;

public class InterruptDemo {
public static void main(String[] args) {
Thread thread1 = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(99999);
}
catch(InterruptedException e) {
System.out.println("I'm interrupted!!");
//e.printStackTrace();
}
}
});

thread1.start();
thread1.interrupt(); // interrupt it right now
}
}

執行結果:
I'm interrupted! 

關於執行緒的wait()、notify()、notifyAll()等方法,在之後的文章中會陸續介紹。