簡單理解線程--阻塞,interrupt


什么是線程

  線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。線程自己基本不擁有資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進行所擁有的所有資源。

阻塞和非阻塞

  阻塞和非阻塞是形容多個線程之間的相互影響的(前提是多線程而不是一個),一個線程占用了臨界區資源,那么其他線程必須在臨界區外等待,阻塞是操作系統層面掛起,上下文切換了,所以性能不高。如果一個線程一直占用不釋放資源,那么其他需要該臨界區資源的線程都必須一直等待。非阻塞就是運行多個線程同時進入臨界區,只要保證不把數據修改壞就行。

阻塞的情況分三種:

  • 等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。
  • 同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程占用,則JVM會把該線程放入鎖池中。
  • 其他阻塞:運行的線程執行sleep()或join()方法時,或者發出I/O請求時,JVM會把該線程置為阻塞狀態。當sleep()狀態超時,join()等待線程終止或者超時,或者I/O處理完畢時,線程重新轉入就緒狀態。
 1 /*   
 2 
 3  * 如果線程被阻塞,它便不能核查共享變量,也就不能停止。這在許多情況下會發生,例如調用  
 4  * Object.wait()、ServerSocket.accept()和DatagramSocket.receive()時,他們都可能永  
 5  * 久的阻塞線程。即使發生超時,在超時期滿之前持續等待也是不可行和不適當的,所以,要使  
 6  * 用某種機制使得線程更早地退出被阻塞的狀態。很不幸運,不存在這樣一種機制對所有的情況  
 7  * 都適用,但是,根據情況不同卻可以使用特定的技術。使用Thread.interrupt()中斷線程  
 8  * Thread.interrupt()方法不會中斷一個正在運行的線程。這一方法  
 9  * 實際上完成的是,在線程受到阻塞時拋出一個中斷信號,這樣線程就得以退出阻塞的狀態。更  
10  * 確切的說,如果線程被Object.wait, Thread.join和Thread.sleep三種方法之一阻塞,那么,  
11  * 它將接收到一個中斷異常(InterruptedException),從而提早地終結被阻塞狀態。因此,  
12  * 如果線程被上述幾種方法阻塞,正確的停止線程方式是設置共享變量,並調用interrupt()(注  
13  * 意變量應該先設置)。如果線程沒有被阻塞,這時調用interrupt()將不起作用;否則,線程就  
14  * 將得到異常(該線程必須事先預備好處理此狀況),接着逃離阻塞狀態。在任何一種情況中,最  
15  * 后線程都將檢查共享變量然后再停止。下面示例描述了該技術。  
16  * */
17 class Example extends Thread {
18 
19     volatile boolean stop = false;
20 
21     public static void main(String args[]) throws Exception {
22         Example thread = new Example();
23 
24         System.out.println("Starting thread...");
25         thread.start();
26         
27         System.out.println("sleep 3S......");
28         Thread.sleep(3000);
29 
30         System.out.println("Asking thread to stop...");
31 
32         /*
33          * 如果線程阻塞,將不會檢查此變量,調用interrupt之后,線程就可以盡早的終結被阻塞狀態,能夠檢查這一變量。
34          */
35         System.out.println("stop==true......");
36         thread.stop = true;
37         
38         
39         /*
40          * 這一方法實際上完成的是,在線程受到阻塞時拋出一個中斷信號,這樣線程就得以退出阻塞的狀態
41          */
42         System.out.println("interrupt......");
43         thread.interrupt();
44         
45         Thread.sleep(3000);
46         System.out.println("Stopping application...");
47         System.exit(0);
48     }
49 
50     public void run() {
51         while (!stop) {
52             System.out.println("Thread running...");
53             try {
54                 System.out.println("sleep  2S......");
55                 Thread.sleep(2000);
56             } catch (InterruptedException e) {
57                 // 接收到一個中斷異常(InterruptedException),從而提早地終結被阻塞狀態
58                 System.out.println("Thread interrupted...");
59             }
60         }
61 
62         System.out.println("Thread exiting under request...");
63     }
64 }

 

把握幾個重點:
stop變量、run方法中的sleep()、interrupt()、InterruptedException。串接起來就是這個意思:
  當我們在run方法中調用sleep(或其他阻塞線程的方法)時,如果線程阻塞的時間過長,比如10s,那在這10s內,線程阻塞,run方法不被執行,但是如果在這10s內,stop被設置成true,表明要終止這個線程,但是,現在線程是阻塞的,它的run方法不能執行,自然也就不能檢查stop,所以線程不能終止,這個時候,我們就可以用interrupt()方法了:我們在thread.stop = true;語句后調用thread.interrupt()方法, 該方法將在線程阻塞時拋出一個中斷信號,該信號將被catch語句捕獲到,一旦捕獲到這個信號,線程就提前終結自己的阻塞狀態,這樣,它就能夠再次運行run方法了,然后檢查到stop = true,while循環就不會再被執行,在執行了while后面的清理工作之后,run方法執行完 畢,線程終止。

http://mp.weixin.qq.com/s/1u95m2EcHFbbJNRv3GJlbQ


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM