最近研究Thread時看到篇好文《Java 理論與實踐: 處理 InterruptedException》,摘錄下來備用:
http://www.ibm.com/developerworks/cn/java/j-jtp05236.html
1,當一個方法拋出 InterruptedException 時,它不僅告訴您它可以拋出一個特定的檢查異常,而且還告訴您其他一些事情。例如,它告訴您它是一個阻塞(blocking)方法,如果您響應得當的話,它將嘗試消除阻塞并盡早返回。
2,當一個方法拋出 InterruptedException 時,它是在告訴您,如果執行該方法的線程被中斷,它將嘗試停止它正在做的事情而提前返回,并通過拋出 InterruptedException 表明它提前返回。 行為良好的阻塞庫方法應該能對中斷作出響應并拋出 InterruptedException,以便能夠用于可取消活動中,而不至于影響響應。
3,如果拋出 InterruptedException 意味著一個方法是阻塞方法,那么調用一個阻塞方法則意味著您的方法也是一個阻塞方法,而且您應該有某種策略來處理 InterruptedException。通常最容易的策略是執行清理,然后自己拋出 InterruptedException,將它傳播給調用者。
4,如果捕捉到 InterruptedException 但是不能重新拋出它,那么應該保留中斷發生的證據,以便調用棧中更高層的代碼能知道中斷,并對中斷作出響應。該任務可以通過調用當前線程的interrupt() 以 “中斷當前線程自己” 來完成。
5,對于執行一個循環中的代碼的任務,通常只需為每一個循環迭代檢查一次中斷。取決于循環執行的時間有多長,任何代碼可能要花一些時間才能注意到線程已經被中斷(或者是通過調用 Thread.isInterrupted() 方法輪詢中斷狀態,或者是調用一個阻塞方法)。
6,不可中斷的阻塞方法:并非所有的阻塞方法都拋出 InterruptedException。輸入和輸出流類會阻塞等待 I/O 完成,但是它們不拋出 InterruptedException,而且在被中斷的情況下也不會提前返回。然而,對于套接字 I/O,如果一個線程關閉套接字,則那個套接字上的阻塞 I/O 操作將提前結束,并拋出一個 SocketException。java.nio 中的非阻塞 I/O 類也不支持可中斷 I/O,但是同樣可以通過關閉通道或者請求 Selector 上的喚醒來取消阻塞操作。
另據別的文章(忘了出處了):
interrupt方法其實只是改變了中斷狀態而已,而sleep、wait和join這些方法的內部會不斷的檢查中斷狀態的值,從而自己拋出InterruptEdException。
——所以該異常從“設置”到“拋出”不是即時的,但是只要調用過程有上述方法之一,就會最終檢測到終端狀態并拋出異常。
Thread類中destory,resume,stop,suspend這些廢棄方法引用了一篇說明文章:
《Why Are Thread.stop, Thread.suspend,Thread.resume and Runtime.runFinalizersOnExit Deprecated?》
http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
以下是根據其寫的demo:
1 /**
2 * @author watchzerg
3 */
4 public class ThreadManager
implements Runnable{
5 //線程對象引用
6 private Thread myThread;
7 //休眠間隔
8 private long interval=1000l;
9 //用volatile保證變量同步
10 private volatile boolean threadSuspended;
11
12 //開始
13 public void start(){
14 myThread=
new Thread(
this,"myThread");
15 myThread.start();
16 }
17
18 /**
19 * 線程體(執行內容):
20 * 如果線程不需要sleep之類的阻塞方法,
21 * 可以通過Thread.isInterrupted()方法來檢測中斷
22 */
23 @Override
24 public void run() {
25 Thread thisThread=Thread.currentThread();
26 while(myThread==thisThread){
27 try{
28 Thread.sleep(interval);
29 System.out.println(myThread.getName()+" is running.");
30 //先if一下,避免每次都進入同步塊帶來的開銷
31 if(threadSuspended&&myThread==thisThread){
32 synchronized(
this){
33 /* 如果線程在suspend狀態被stop,那么myThread==null
34 * 它在下一個循環就快速退出,不再等待了
35 * 不過話說,wait方法本身也會拋中斷異常的
36 * 所以我覺得這里去掉"myThread==thisThread"也行
37 * 元方,你怎么看?
38 * */
39 while(threadSuspended&&myThread==thisThread){
40 wait();
41 }
42 }
43 }
44 }
catch(InterruptedException e){
45 System.out.println(thisThread.getName()+
46 " is interrupted by InterruptedException.");
47 //如果這里不打算處理此異常,而又無法拋出去,可以重新斷言自己:
48 //Thread.currentThread().interrupt();
49 }
50 }
51 System.out.println(thisThread.getName()+": I'm out, do you copy? ");
52 }
53
54 /**
55 * 停止線程:
56 * 如果是sleep狀態,是interrupt起作用;
57 * 如果是運行狀態,是myThread==null終止了循環
58 */
59 public synchronized void stop(){
60 if(myThread==
null){
61 return;
62 }
63 Thread moribund=myThread;
64 myThread=
null;
65 moribund.interrupt();
66 }
67
68 /**
69 * 掛起線程:
70 * 反轉條件,并通知其它等待線程
71 */
72 public synchronized void suspend(){
73 threadSuspended=!threadSuspended;
74 if(!threadSuspended){
75 notify();
76 }
77 }
78
79 //test
80 public static void main(String[] args)
throws Exception {
81 ThreadManager manager=
new ThreadManager();
82 //開始
83 manager.start();
84 System.out.println("sys:starting

");
85 Thread.sleep(10000l);
86 //暫停
87 manager.suspend();
88 System.out.println("sys:suspend

");
89 Thread.sleep(10000l);
90 //恢復
91 manager.suspend();
92 System.out.println("sys:resume

");
93 Thread.sleep(10000l);
94 //暫停
95 manager.suspend();
96 System.out.println("sys:suspend

");
97 Thread.sleep(5000l);
98 //在暫停狀態下停止
99 manager.stop();
100 System.out.println("sys:stop

");
101 Thread.sleep(10000l);
102 //退出
103 System.out.println("sys:exit

now what?");
104 }
105 }