Java 如何中斷和恢復線程的執行

 

 

1、線程的狀態html

 

線程能夠阻塞於四種狀態:java

一、當線程執行Thread.sleep()時,它一直阻塞到指定的毫秒時間以後,或者阻塞被另外一個線程打斷;linux

二、當線程碰到一條wait()語句時,它會一直阻塞到接到通知notify()、被中斷、通過了指定時間爲止(如有超時值的話)jvm

三、線程阻塞與不一樣I/O的方式函數

    3.1. 常見的一種方式是InputStream的read()方法,該方法一直阻塞到從流中讀取一個字節的數據爲止,它能夠無限阻塞,所以不能指定超時時間;post

  3.2 java.nio 中的非阻塞 I/O 類也不支持可中斷 I/O,可是一樣能夠經過關閉通道或者請求 Selector 上的喚醒來取消阻塞操做this

四、線程也能夠阻塞等待獲取某個對象鎖的排他性訪問權限(即等待得到synchronized語句必須的鎖時阻塞)。url

注意,並不是全部的阻塞狀態都是可中斷的,以上阻塞狀態的前兩種能夠被中斷,後兩種不會對中斷作出反應spa

 

wait vs blocked操作系統


假設t1,t2前後兩個線程,都執行以下代碼:
synchronized(Obj) { Obj.wait(); } 

t1先進,最後在Obj.wait()下卡住,這時java管t1的狀態waitting狀態

t2後進,直接在第一行就卡住了,這時java叫t2爲blocked狀態。

請注意,blocked是過去分詞,意味着他是被卡住的。由於這段代碼只讓一條線程運行。同時,jvm是知道怎麼結束blocked的,只要別的線程退出這段代碼,他就會自動讓你進去。也就是說別的線程無需喚醒你,由jvm自動來幹

而waiiting是說我調用wait()等函數,主動卡住本身(我在等一個白富美),請jvm在知足某種條件後(白富美髮消息讓咱們晚上見),好比另條線程調用了notify()後,把我喚醒。這個喚醒的責任在於別的線程(白富美)明確的調用一些喚醒函數。

作這樣的區分,是jvm出於管理的須要,作了這種區分,好比兩個緣由的線程放兩個隊列裏管理,若是別的線程運行出了synchronized這段代碼,我只須要去blocked隊列,放個出來。而某人調用了notify(),我只須要去waitting隊列裏取個出來。

P.S. 從linux內核來看,這些線程都是等待狀態,沒區別,區別只在於java的管理須要。一般咱們在系統級別說線程的blocked,是說線程操做io,被暫停了,這種線程由linux內核來喚醒(io設備報告數據來了,內核把block的線程放進可運行的進程隊列,
 
依次獲得處理器時間),而wait是說,等待一個內核mutex對象,另個線程signal這個mutex後,這個線程才能夠運行。 區別在於由誰喚醒,是操做系統,仍是另外一個線程,這裏倒和java很類似。

 

 

2、中斷某個線程

當對一個線程,調用 interrupt() 時

① 若是線程處於正常活動狀態,那麼會將該線程的中斷標誌設置爲 true。被設置中斷標誌的線程將繼續正常運行,不受影響。

② 若是線程處於被阻塞狀態(sleep, wait, join 等狀態),那麼線程將當即退出被阻塞狀態,並拋出一個InterruptedException

interrupt() 並不能真正的中斷線程,須要被調用的線程本身進行配合才行

① 在正常運行任務時,常常檢查本線程的中斷標誌位,若是被設置了中斷標誌就自行中止線程

② 在調用阻塞方法時正確處理InterruptedException異常

 

1。當線程沒有處於阻塞狀態,經過改變標誌量,可讓線程中止。

 1 public class Example01 extends Thread {
 2     boolean  stop=false;
 3     public static void main( String args[] ) throws Exception {
 4         Example01 thread = new Example01();
 5         thread.start();
 6         Thread.sleep(1000);
 7         thread.interrupt(); //線程不會中止
 8 //      thread.stop = true;  //線程會中止
 9     }
10     public void run() {
11         while(!stop){
12             System.out.println( "Thread is running..." );
13             
14         }
15         System.out.println("Thread exiting..." );
16         }
17 }

 

2。當線程處於阻塞狀態,調用interrupt()方法。

  If this thread is blocked in an invocation of the wait() methods of the Object class, or of the join(), , sleep(long)methods of

Thread class, then its interrupt status will be cleared and it will receive an InterruptedException.

 1 public class Example01 extends Thread {
 2     boolean  stop=false;
 3     public static void main( String args[] ) throws Exception {
 4         Example01 thread = new Example01();
 5         thread.start();
 6         Thread.sleep(1000);
 7         thread.interrupt(); 
 8         
 9     }
10     public void run() {                
11         System.out.println("-------sleeping");
12         try {
13             Thread.sleep(2000);
14         } catch (InterruptedException e) {
15             e.printStackTrace();
16         }
17         System.out.println("-------caclulating");
18         double d = 0; 
19         for(int i=1; i<2500000; i++){
20             d += Math.E/d;
21         }
22         System.out.println("-------finish caclulating");        
23     
24     }
25 }

 

3.當線程處於阻塞狀態,能夠中斷等待的資源,如I/O, Socket

 

參考:

IBM: 處理InterruptedException

self: AQS 與 LockSupport

相關文章
相關標籤/搜索