★ 線程狀態(tài)
Java虛擬機將線程運行過程分成四種狀態(tài) 。 (1) New 新生,;(2) Runnable 可運行,;(3) Blocked 阻塞;(4) Dead 死亡,。
值得注意的是: 線程的可運行狀態(tài)并不代表線程一定在運行(runnable != running ) ,。 大家都知道:所有現(xiàn)代桌面和服務(wù)器操作系統(tǒng)都使用了搶占式的線程調(diào)度策略 。一旦線程開始執(zhí)行,,并不是總是保持持續(xù)運行狀態(tài)的,。當系統(tǒng)分給它的時間片(非常小的運行時間單位)用完以后,不管程序有沒有執(zhí)行完,,線程被強制放棄CPU,,進入就緒狀態(tài),直到下次被調(diào)度后開始繼續(xù)執(zhí)行,。也就是說,, Runnable可運行狀態(tài)的線程處于兩種可能的情況下:(1)占用CPU運行中,(2)等待調(diào)度的就緒狀態(tài),。 這里要聲明一下:處于等待調(diào)度的就緒狀態(tài)線程和處于阻塞的線程是完全不同的,。就緒的線程是因為時間片用完而放棄CPU,其隨時都有可能再次獲得CPU而運行,,這一切取決于分時OS的線程調(diào)度策略,。
在很多操作系統(tǒng)的專業(yè)術(shù)語中,這種因時間片用完而被剝奪CPU的情況我們叫做線程中斷 ,。注意這和我們下面要將得中斷線程是兩個完全不同的概念,。事實上,我們不可能通過應(yīng)用程序來控制CPU的線程中斷,,除非我們能夠自由調(diào)用OS的內(nèi)核,。
★ 中斷線程 —— interrupt()
一個正在運行的線程除了正常的時間片中斷之外,能否被其他線程控制,?或者說其他線程能否讓指定線程放棄CPU或者提前結(jié)束運行,? 除了線程同步機制之外,,還有兩種方法: (1) Thread.stop(), Thread.suspend(), Thread.resume() 和Runtime.runFinalizersOnExit() 這些終止線程運行的方法 。這些方法已經(jīng)被廢棄,,使用它們是極端不安全的,。 (2) Thread.interrupt() 方法是很好的選擇。但是使用的時候我們必須好好理解一下它的用處,。
-
- class TestRunnable implements Runnable{
- public void run(){
- while(true)
- {
- System.out.println( "Thread is running..." );
- long time = System.currentTimeMillis();
- while((System.currentTimeMillis()-time < 1000)) {
-
- }
- }
- }
- }
- public class ThreadDemo{
- public static void main(String[] args){
- Runnable r=new TestRunnable();
- Thread th1=new Thread(r);
- th1.start();
- th1.interrupt();
- }
- }
- /運行結(jié)果:一秒鐘打印一次Thread is running...,。程序沒有終止的任何跡象
//無法中斷正在運行的線程代碼
class TestRunnable implements Runnable{
public void run(){
while(true)
{
System.out.println( "Thread is running..." );
long time = System.currentTimeMillis();//去系統(tǒng)時間的毫秒數(shù)
while((System.currentTimeMillis()-time < 1000)) {
//程序循環(huán)1秒鐘,,不同于sleep(1000)會阻塞進程。
}
}
}
}
public class ThreadDemo{
public static void main(String[] args){
Runnable r=new TestRunnable();
Thread th1=new Thread(r);
th1.start();
th1.interrupt();
}
}
//運行結(jié)果:一秒鐘打印一次Thread is running...,。程序沒有終止的任何跡象
上面的代碼說明interrupt()并沒有中斷一個正在運行的線程,,或者說讓一個running中的線程放棄CPU。那么interrupt到底中斷什么,。
首先我們看看interrupt究竟在干什么,。
當我們調(diào)用th1.interrput()的時候,線程th1的中斷狀態(tài)(interrupted status) 會被置位,。我們可以通過Thread.currentThread().isInterrupted() 來檢查這個布爾型的中斷狀態(tài),。
在Core Java中有這樣一句話:"沒有任何語言方面的需求要求一個被中斷的程序應(yīng)該終止。中斷一個線程只是為了引起該線程的注意,,被中斷線程可以決定如何應(yīng)對中斷 ",。好好體會這句話的含義,,看看下面的代碼:
-
- public void run(){
- try{
- ....
- while(!Thread.currentThread().isInterrupted()&& more work to do){
-
- }
- }catch(InterruptedException e){
-
- }
- finally{
-
- }
- }
//Interrupted的經(jīng)典使用代碼
public void run(){
try{
....
while(!Thread.currentThread().isInterrupted()&& more work to do){
// do more work;
}
}catch(InterruptedException e){
// thread was interrupted during sleep or wait
}
finally{
// cleanup, if required
}
}
很顯然,,在上面代碼中,while循環(huán)有一個決定因素就是需要不停的檢查自己的中斷狀態(tài),。當外部線程調(diào)用該線程的interrupt 時,,使得中斷狀態(tài)置位。這是該線程將終止循環(huán),,不在執(zhí)行循環(huán)中的do more work了,。
這說明: interrupt中斷的是線程的某一部分業(yè)務(wù)邏輯,前提是線程需要檢查自己的中斷狀態(tài)(isInterrupted()),。
但是當th1被阻塞的時候,,比如被Object.wait, Thread.join和Thread.sleep三種方法之一阻塞時。調(diào)用它的interrput()方法,??上攵瑳]有占用CPU運行的線程是不可能給自己的中斷狀態(tài)置位的,。這就會產(chǎn)生一個InterruptedException異常,。
-
- class TestRunnable implements Runnable{
- public void run(){
- try{
- Thread.sleep(1000000);
- }catch(InterruptedException e){
- e.printStackTrace();
-
- }
- }
- }
- public class TestDemo2{
- public static void main(String[] args) {
- Runnable tr=new TestRunnable();
- Thread th1=new Thread(tr);
- th1.start();
- while(true){
- th1.interrupt();
- }
- }
- }
-
-
-
-
-
|