1. 程式人生 > >Java多執行緒學習筆記(一)之中斷中的Interrupt,interrupted(),isInterrupted()

Java多執行緒學習筆記(一)之中斷中的Interrupt,interrupted(),isInterrupted()

  • 1、關於中斷

在Java中中斷最初是通過stop()來終止執行緒的,後來發現這樣簡單粗暴的停止執行緒會產生很多問題(例如物件monitor的釋放),所以改為deprecated,推薦使用interrupt()來中斷執行緒。而對於執行緒來說,會持有一個interrupted標記變數,呼叫interrupt()方法並不會使執行緒立即中斷,而是把標記變數設定為true,而對於執行緒的中斷則需要自己去作處理。下面這段程式碼可以說明:

class ThreadTest1{
	public static void main(String[] args) throws InterruptedException {
		Thread thread = new Thread() {
			@Override
			public void run() {
				for (int i = 0; true; i++) {
					System.out.println("Thread is running " + i);
				}
			}
		};
		thread.start();
		Thread.sleep(1);
		thread.interrupt();
		/**
		 * 輸出:
		 *  Thread is running 0
			Thread is running 1
			Thread is running 2
			Thread is running 3
			Thread is running 4
			Thread is running 5
			Thread is running 6
			Thread is running 7
			Thread is running 8
			Thread is running 9
			Thread is running 10
			Thread is running 11
			Thread is running 12
			Thread is running 13
			Thread is running 14
			Thread is running 15
			Thread is running 16
			Thread is running 17
			...
		 */
	
}

執行緒會一直無限執行。

  • 2、利用中斷標記來手動中斷執行緒

那麼對於上面的程式碼我們如何做到中斷執行緒呢?上面說到,呼叫interrupt()方法後,會把執行緒的中斷標記設定為true,我們可以利用這個標記來進行手動的判斷中斷執行緒。以下是修改後的程式碼:


		Thread thread = new Thread() {
			@Override
			public void run() {
				for (int i = 0; true; i++) {
					if (this.isInterrupted()) {
						System.out.println("This thread is interrupted.");
						break;
					}
					System.out.println("Thread is running " + i);
				}
			}
		};
		thread.start();
		Thread.sleep(1);
		thread.interrupt();
		/**
		 * 輸出:
		 *  Thread is running 0
			Thread is running 1
			Thread is running 2
			Thread is running 3
			Thread is running 4
			Thread is running 5
			Thread is running 6
			Thread is running 7
			Thread is running 8
			Thread is running 9
			Thread is running 10
			Thread is running 11
			Thread is running 12
			Thread is running 13
			Thread is running 14
			Thread is running 15
			Thread is running 16
			Thread is running 17
			This thread is interrupted.
		 */
	

我們在迴圈里加入了一箇中斷標識的判斷,一旦中斷標識為true,立刻停止迴圈,從而中斷執行緒。同樣的,除了isInterrupted(),用Thread.interrupted()效果也是一樣的。

  • 3、關於獲取中斷標記,interrupted()和isInterrupted()的區別

獲取中斷標記有兩個方法,一個是Thread.interrupted(),另外一個是this.isInterrupted()。前者是靜態方法,後者是例項方法,下面是二者的原始碼:

可以看到二者都是呼叫了isInterrupted(boolean)這個本地方法,而這個本地方法會根據引數來選擇是否重置interrupted state。就是說isInterrupted()不會重置中斷狀態,而interrupted()會重置狀態。下面我們通過程式碼測試一下:

	public static void main(String[] args) throws InterruptedException {

		Thread thread = new Thread() {
			
			@Override
			public void run() {
				while (true) {
					if (Thread.interrupted()) {
						break;
					}
					
					System.out.println("執行緒未被中斷,當前執行緒狀態:" + this.isInterrupted());
					
				}
				System.out.println("************執行緒已被中斷,當前執行緒狀態:" + this.isInterrupted());
			}
		};
		
		thread.start();
		Thread.sleep(1);
		thread.interrupt();
		/*
		 *  執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
		 	************執行緒已被中斷,當前執行緒狀態:false
		 */
	
	}

 我們先看isInterrupted()的效果,線上程執行的最後,執行緒已經中斷,執行緒的中斷標記狀態為false,而因為列印該行,說明已經跳出了while迴圈,說明if語句為真,也就是Thread.interrupted()返回true,但最後已經被重置了。那麼下面我們繼續看看isInterrupted()的效果,程式碼如下:

public static void main(String[] args) throws InterruptedException {
		Thread thread = new Thread() {
			
			@Override
			public void run() {
				while (true) {
					if (isInterrupted()) {
						break;
					}
					
					System.out.println("執行緒未被中斷,當前執行緒狀態:" + this.isInterrupted());
					
				}
				System.out.println("************執行緒已被中斷,當前執行緒狀態:" + this.isInterrupted());
			}
		};
		
		thread.start();
		Thread.sleep(1);
		thread.interrupt();
		/*
		 *  執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			執行緒未被中斷,當前執行緒狀態:false
			************執行緒已被中斷,當前執行緒狀態:true
		 */
	}

可以看到,我們只是把if語句裡的條件改了一下,其他位置並沒有改變,但是最後執行緒的狀態為true,說明interrupt()方法正如所說的那樣,把執行緒中斷標識改為了true。

  • 說在最後

如果文章有疏漏,請及時指出,大家相互交流學習,謝謝。

  • 參考文章