start方法是對應(yīng)啟動操作的方法,其具體功能是為線程分配必要的系統(tǒng)資源,將線程設(shè)置為可運行狀態(tài),從而可以使系統(tǒng)調(diào)度這個線程。
2.2 可運行(runnable)狀態(tài)
如果對一個處于創(chuàng)建狀態(tài)的線程進行啟動操作,則此線程便進入可運行狀態(tài)。比如,用下列語句
myThread.start();
則使線程myThread進入可運行狀態(tài)。上述語句實質(zhì)上是調(diào)用了線程體即run()方法,注意,run()方法包含在myThread線程中,也就是先由java.lang包的Thread類將run()方法傳遞給子類MyThreadClass(),再通過創(chuàng)建線程由子類MyThreadClass,傳遞給線程myThread。
線程處于可運行狀態(tài)只說明它具備了運行條件,但可運行狀態(tài)并不一定是運行狀態(tài),因為在單處理器系統(tǒng)中運行多線程程序,實際上在一個時間點只有一個線程在運行,而系統(tǒng)中往往有多個線程同時處于可運行狀態(tài),系統(tǒng)通過快速切換和調(diào)度使所有可運行線程共享處理器,造成宏觀上的多線程并發(fā)運行?梢,一個線程是否處于運行狀, 除了必須處于可運行狀態(tài)外,還取決于系統(tǒng)的調(diào)度。
在可運行狀態(tài)可以進行多種操作,最通常的是從run()方法正常退出而使線程結(jié)束,進入消亡狀態(tài)。 此, 還可以有如下操作
掛起操作,通過調(diào)用suspend方法來實現(xiàn);
睡眠操作,通過調(diào)用sleep方法來實現(xiàn);
等待操作,通過調(diào)用wait方法來實現(xiàn);
退讓操作,通過調(diào)用yield方法來實現(xiàn);
終止操作,通過調(diào)用stop方法來實現(xiàn)。
前面三種操作都會使一個處于可運行狀態(tài)的線程進入不可運行狀態(tài)。比如,仍以myThread線程為例,當(dāng)其處于可運行狀態(tài)后,再用如下語句
myThread.sleep (5000);
則調(diào)用sleep方法使myThread線程睡眠5s(5000ms)。這5s內(nèi),此線程不能被系統(tǒng)調(diào)度運行,只有過5s后,myThread線程才會醒來并自動回到可運行狀態(tài)。
如果一個線程被執(zhí)行掛起操作而轉(zhuǎn)到不可運行狀態(tài),則必須通過調(diào)用恢復(fù)(resume)操作,才能使這個線程再回到可運行狀態(tài)。
退讓操作是使某個線程把CPU控制權(quán)提前轉(zhuǎn)交給同級優(yōu)先權(quán)的其他線程。
對可運行狀態(tài)的線程也可以通過調(diào)用stop方法使其進入消亡狀態(tài)。
2.3 不可運行(not runnable)狀態(tài)
不可運行狀態(tài)都是由可運行狀態(tài)轉(zhuǎn)變來的。一個處于可運行狀態(tài)的線程,如果遇到掛起(suspend)操作、睡眠(sleep)操作或者等待(wait)操作,就會進入不可運行狀態(tài)。 另外,如果一個線程是和I/O操作有關(guān)的,那么,在執(zhí)行I/O指令時,由于外設(shè)速度遠遠低于處理器速度而使線程受到阻, 從而進入不可運行狀態(tài),只有外設(shè)完成輸入/輸出之后,才會自動回到可運行狀態(tài)。線程進入不可運行狀態(tài)后,還可以再回到可運行狀態(tài),通常有三種途徑使其恢復(fù)到可運行狀態(tài)。
一是自動恢復(fù)。通過睡眠(sleep)操作進入不可運行狀態(tài)的線程會在過了指定睡眠時間以后自動恢復(fù)到可運行狀態(tài),由于I/O阻塞而進入不可運行狀態(tài)的線程在外設(shè)完成I/O操作后,自動恢復(fù)到可運行狀態(tài)。
二是用恢復(fù)(resume)方法使其恢復(fù)。如果一個線程由于掛起(suspend)操作而從可運行狀態(tài)進入不可運行狀態(tài),那么,必須用恢復(fù)(resume)操作使其再恢復(fù)到可運行狀態(tài)。
三是用通知(notify或notifyAll)方法使其恢復(fù)。如果一個處于可運行狀態(tài)的線程由于等待(wait)操作而轉(zhuǎn)入不可運行狀態(tài),那么,必須通過調(diào)用notify方法或notifyAll方法才能使其恢復(fù)到可運行狀態(tài),采用等待操作往往是由于線程需要等待某個條件變量,當(dāng)獲得此條件變量后,便可由notify或ontifyAll方法使線程恢復(fù)到可運行狀態(tài)。
恢復(fù)到可運行狀態(tài)的每一種途徑都是有針對性的,不能交叉。比如,對由于阻塞而進入不可運行狀態(tài)的線程采用恢復(fù)操作將是無效的。
在不可運行狀態(tài),也可由終止(stop)操作使其進入消亡狀態(tài)。
2.4 消亡(dead)狀態(tài)
一個線程可以由其他任何一個狀態(tài)通過終止(stop)操作而進入消亡狀態(tài)。 線程一旦進入消亡狀態(tài),那它就不再存在了,所以也不可能再轉(zhuǎn)到其它狀態(tài)。
通常,在一個應(yīng)用程序運行時,如果通過其它外部命令終止當(dāng)前應(yīng)用程序,那么就會調(diào)用(stop)方法終止線程。但是,最正常、最常見的途徑是由于線程在可運行狀態(tài)正常完成自身的任務(wù)而″壽終正寢″,從而進入消亡狀態(tài),這個完成任務(wù)的動作是由run方法實現(xiàn)的。
3 Java線程的兩種創(chuàng)建途徑
一種途徑是通過對Thread的繼承來派生一個子類,再由此子類生成一個對象來實現(xiàn)線程的創(chuàng)建,這是比較簡單直接的辦法。Thread類包含在系統(tǒng)API提供的8個軟件包之一Java.lang中,Thread類中包含了很多與線程有關(guān)的方, 其中,一個名為run的方法就是用來實現(xiàn)線程行為的。比如:
1 import java.lang.* //引用lang包
2 class Mango exteds Thread {
3 public void run() {
4 ......
5 }
6 }
上述程序段中,第1行語句引用軟件包lang,這樣做是為了給編譯器一個信息,從而使后面程序中有關(guān)lang包中的方法可直接用方法名,而不必帶前綴“Java.lang”。第2行語句是從lang包Thread派生一個子類Mango, 而這個子類中提供了run方法的實現(xiàn),這樣,運行時,將由子類Mango 的 run方法置換父類Thread的run方法。
不過這一步還沒有創(chuàng)建線, 必須由子類生成一個對象,并且進行啟動操作,這樣才能得到一個處于可運行狀態(tài)的線程。生成對象其實就是完成線程的創(chuàng)建,而啟動是對已創(chuàng)建的線程進行操作。具體語句如下:
Mango t=new Mango();
t.start();
上面先用關(guān)鍵字new使線程進入創(chuàng)建狀態(tài),又調(diào)用start()方法使線程進入可運行狀態(tài)。注意,start()方法是由Thread繼承給子類Mango、然后又在生成對象時由對象t從類Mango得到的。
另一種途徑是通過一個類去繼承接口runnable來實現(xiàn)線程的創(chuàng)建 而這個類必須提供runnable接口中定義的方法run()的實現(xiàn)。runnable是Java.lang包中的一個接口,在runnable接口中,只定義了一個抽象方法run()。所以,如用這種途徑來創(chuàng)建線程,則應(yīng)先由一個類連接接口runnable,并且提供run()方法的實現(xiàn)。比如,下面的程序段實現(xiàn)了與接口的連接。
1 public class xyz implements Runnable{
2 int i;
3 public voed run(){
4 while (true){
5 System.out.println("Hello"+i++);
6 }
7 }
8 }
然后再創(chuàng)建一個線程
runnable r=new xyz();
Thread t=new Thread(r);
這種途徑創(chuàng)建線程比第一種途徑靈活。當(dāng)一個類既需要繼承一個父類又要由此創(chuàng)建一個線程時,由于Java不支持多重繼承,這樣,用第一種途徑將行不通,因為,按此思路創(chuàng)建線程也是以繼承的方法實現(xiàn)的。 于是,就需要一個類既繼承Thread類,又繼承另一個父類。但用接口方法卻能實現(xiàn)這個目標(biāo)。
4 線程的啟動和終止
Thread的start()方法對應(yīng)于啟動操作,它完成兩方面的功能:一方面是為線程分配必要的資源,使線程處于可運行狀態(tài),另一方面是調(diào)用線程的run()方法置換Thread的中run()方法或者置換runnable中的run()方法來運行線程。
使用start()方法的語句很簡單,即:
ThreadName.start();
下面的程序段先創(chuàng)建并啟動線程myThread, 然后使用sleep()方法讓其睡眠20000ms即20s,使其處于不可運行狀態(tài),過20s后,線程又自動恢復(fù)到可運行狀態(tài)。
Thread MyThread=new MyThreadClass();
MyThread.start();
try{
MyThread.sleep(20000);
}
catch(InterrujptedException e){ }





