當1個線程被創建并啟動以后,其實不是1開始就處于履行狀態,已不是1直處于運行狀態。線程也是有生命周期的,包括:創建(New)、就緒(Runnable)、阻塞(Blocked)、運行(Running)、死亡(Dead)5種狀態。當線程運行時,也不可能1直霸占著CPU獨自運行,而是1直在運行、就緒狀態之間切換。
當程序通過new創建1個線程時,這個線程就處于新建(New)狀態了,不過這個時候該線程并沒有表現出線程的任何特點,和其他的普通java對象1樣,java虛擬機為其分配內存,并初始化其變量的值。
當線程對象調用了start()方法以后,該線程就進入了就緒狀態,此時還不是運行狀態,java虛擬機為其創建方法調用棧和程序計數器,此時的線程表示可以運行了,但是具體甚么時候運行,還需要等待jvm的調度。
有1個需要注意的地方,啟動1個線程需要調用的是start()方法,而不是用run()來啟動線程,如果直接調用run方法的話,系統會把線程當做1個普通的對象,run()方法也只是1個普通的方法。給大家舉個栗子:
package lifecycle;
public class InvokeRun extends Thread{
private int i;
public void run(){
for(;i<100;i++){
System.out.println(Thread.currentThread().getName() + " " +i);
}
}
public static void main(String[] args){
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName() + " " +i);
if(i==20){
new InvokeRun().run();
new InvokeRun().run();
}
}
}
}
當啟動線程的時候直接用run()
方法,終究的結果是:全部程序的運行只有1個線程。程序編程了單線程的了。主要是由于,當你啟動線程的時候,如果調用的start()
方法,系統會把run()
方法當做線程的履行體。直接調用run()
方法的話,在run()
方法返回之前其他線程沒法并發運行。
只能對處于新建狀態的線程調用start()方法,否則將引發IllegalThreadStateException異常
當1個就緒的線程取得CPU以后,就進入了運行狀態,系統如果只有1個CPU的話,就會出現多個線程在同1個CPU上輪換的現象,1個CPU在任什么時候間只有1個線程在運行。如果有多個CPU的話,就會出現多個線程并行(parallel)履行;
1個線程不可能1直處于運行狀態,除非這個線程在足夠短的時間內就可以履行完成,否則的話,線程在履行的進程中都會被中斷數次,目的是為了給其他的線程履行的機會,具體的需要斟酌后臺的履行策略。
上圖是線程的狀態轉換圖,通過上圖我們就能夠了解到,線程是在甚么條件下進入到阻塞(Blocked)狀態,又在甚么條件下進入到就緒(Runnable)狀態;通過上圖還可以了解到1點,線程其實不是直接從運行狀態轉到就緒狀態的,除yield()
方法。
線程會以下面3種方式結束,結束后就是死亡狀態。
run()
或call()
方法履行完成,線程正常結束。Exception
或Error
。stop()
方法來結束該線程—-該方法通常容易致使死鎖,不推薦使用。當線程死亡以后,其他的線程其實不受其影響,而結束。其他的子線程啟動以后,它的地位和主線程是同等的,不受主線程的影響。
如何測試1個線程是不是已死亡?用線程對象的isAlive()
方法來測,當線程處于就緒、運行、阻塞狀態時,返回的結果是true
,當線程處于死亡、新建狀態時返回的是false
。下面舉1個對已死的線程調用start()
方法的例子:
package startDead;
public class StartDead extends Thread {
private int i;
public void run(){
for(;i<100;i++){
System.out.println(getName()+" "+i);
}
}
/**
* @param args
*/
public static void main(String[] args) {
StartDead sd =new StartDead();
for(int i=0;i<300;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
if(i==20){
sd.start();
System.out.println(sd.isAlive());
}
//當i>20的時候,線程肯定已啟動過了,如果sd.isAlive()為假時,那就是死亡狀態了;
if(i>20 && !sd.isAlive()){
//試圖再次啟動線程
sd.start();
}
}
}
}
對已死亡的線程調用start()
方法,會拋出IllegalThreadStateException異常。
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.start(Thread.java:595)
at startDead.StartDead.main(StartDead.java:27)
不要試圖對已死亡的線程調用start()方法,死亡就是死亡,死亡的線程不會再次被當做線程的履行體。程序只能對處于新建狀態的線程調用start()方法,對處于新建狀態的線程兩次調用start()也是毛病的,這都會引發IllegalThreadStateException異常