1. 程式人生 > >java併發:執行緒中斷

java併發:執行緒中斷

一共三個方法.

Thread.interrupt();//就是嘗試中斷本執行緒.將新增中斷標誌
Thread.isInterrupted();//檢視本執行緒的中斷標誌,代表是否被中斷.
Thread.static.interrupted();//靜態方法,嘗試中斷本執行緒,但是中斷標誌會被清除.

 

看如下兩段程式碼:

private void aaa() throws InterruptedException {
		Thread t = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println(Thread.currentThread().isInterrupted());//false				
				Thread.currentThread().interrupt();//嘗試中斷,新增中斷標誌
				System.out.println(Thread.currentThread().isInterrupted());//true
			}
		});
		t.start();
	}
private void bbb() throws InterruptedException {
		Thread t = new Thread(new Runnable() {
			@Override
			public void run() {
				System.out.println(Thread.currentThread().isInterrupted());//false
				Thread.interrupted();//嘗試中斷,清空中斷標誌
				System.out.println(Thread.currentThread().isInterrupted());//false
			}
		});
		t.start();
	}

 可以看到他們的區別.

但是一個新的問題產生了.不是中斷了嗎?為什麼後面的列印還可以執行?

 

好吧.這個得需要看文件.

文件上說了該中斷方法會自上而下判斷,如果符合條件,則執行該措施,且不向下穿透..

1.如果是其他執行緒呼叫該執行緒的中斷,將執行checkAccess()方法,這可能會引起SecurityException.如果是執行緒本身呼叫自身的中斷則沒問題.

2.如果此時執行緒被wait(),join(),sleep()阻塞,那麼將會丟擲異常InterruptedException.中斷狀態清除.但LockSupport.part()沒有說.

3.如果此時執行緒在IO中被阻塞,那麼流通道將關閉,將丟擲 java.nio.channels.ClosedByInterruptException.設定為中斷狀態.

4.如果此時執行緒在java.nio.channels.Selector中阻塞,那麼執行緒將結果立即返回.設定為中斷狀態.

5.如果以上條件都不成立,則設定為中斷狀態.

而我們上面的舉例貌似只有第五條符合,也就是隻是設定為中斷狀態,其他都不會做.

我們再來看一個例子:這個例子就會符合上面第二條.丟擲異常.狀態清除.

其實丟擲異常是終止執行緒的一個不錯的方法.但要記得清理資源.更要注意異常會釋放鎖

private void sleep() throws InterruptedException {
		Thread t = new Thread(new Runnable() {	
			@Override
			public void run() {
                
				System.out.println(Thread.currentThread().isInterrupted());//此時還主執行緒在sleep還未執行中斷,false
				try {
					Thread.currentThread().sleep(20000);//在這裡被中斷,拋異常
					System.out.println(Thread.currentThread().isInterrupted());//上句拋異常,這裡就不會執行了.
				} catch (InterruptedException e) {
                    
					System.out.println(Thread.currentThread().isInterrupted());//中斷標誌被清除,false
					e.printStackTrace();
				}
				
			}
		});
		t.start();
		Thread.sleep(1000);
		t.interrupt();
	}

再來個例子,看下io阻塞的情況,實際上這玩意跟上面說的第三個規則根本不一樣

private void read() throws InterruptedException {
		Runnable runnable = new Runnable() {	
			@Override
			public void run() {
				try {
					System.in.read();
				} catch (IOException e) {
					
					e.printStackTrace();
				}
				
			}
		};
		Thread t = new Thread(runnable);
		t.start();
		Thread.sleep(1000);
		t.interrupt();//完全沒有用,該被阻塞的還是被阻塞,根本不拋異常.
	}

書中好像說了阻塞流和synchronized這倆根本不會受到interrupt()的影響;

 

還有一個疑問.以上5個規則,一般都是命中第五個,可說第五個只是設定了中斷狀態,有什麼意義呢?

其實可以這樣用.

private void ccc() throws InterruptedException {
		Runnable runnable = new Runnable() {	
			@Override
			public synchronized void run() {
				while(true){
					if (Thread.currentThread().isInterrupted()){
						//如果設定為中斷,結束執行
						return;
					}
					//業務程式碼
				}
			}
		};
		Thread t = new Thread(runnable);
		t.start();
		Thread.sleep(3000);
		t.interrupt();//命令執行緒中斷執行
	}