1. 程式人生 > >java執行緒學習(三):執行緒中斷 interrupt() 方法的使用

java執行緒學習(三):執行緒中斷 interrupt() 方法的使用

上一章節中,我們對執行緒終止stop方法進行了講解,stop終止執行緒的方法已經被丟棄,原因是執行緒的終止太暴力,會導致不必要的資料錯誤,所以stop方法在不自信的情況下,慎用慎用。。。。同時,也提供了較為完善的終止方案了。
本節就來學習執行緒中斷 interrupt() 方法的使用:
一、先來看看原始碼

	public void interrupt() {
		if (this != currentThread()) {
			this.checkAccess();
		}

		Object var1 = this.blockerLock;
		synchronized (this.blockerLock) {
			Interruptible var2 = this.blocker;
			if (var2 != null) {
				this.interrupt0();
				var2.interrupt(this);
				return;
			}
		}

		this.interrupt0();
	}

	public static boolean interrupted() {
		return currentThread().isInterrupted(true);
	}

	public boolean isInterrupted() {
		return this.isInterrupted(false);
	}

可以看出目前跟中斷相關的有三個方法,分別是:

  • interrupt(): 例項方法。它通知目標執行緒中斷,也就是設定中斷標誌位(中斷標誌位表示當前執行緒已經被中斷了)。
  • isInterrupted():例項方法。用來判斷當前執行緒是否有被中斷(通過檢查中斷標誌位)
  • interrupted():靜態方法。用來判斷當前執行緒的中斷狀態,並清除當前執行緒的中斷標誌為狀態。

二、我們來看看這些例子加理解:

栗子一:只使用interrupt()方法:

public class Interrupt_demo {
	
	/**
	 * 例子1:
	 * 只使用interrupt方法
	 * @author fei
	 *
	 */
	public static class Interrupt_demo1 extends Thread{

		@Override
		public void run() {
			System.out.println("執行緒"+Thread.currentThread().getName()+"在執行~~~~");
			Thread.yield();
		}
	}
	
	public static void main(String[] args) {	
		//建立10條執行緒
		for (int i = 0; i < 10; i++) {
			Thread thread=new Interrupt_demo1();
			thread.start();
			//如果是偶數,那麼就中斷
			if (i%2==0) {
				thread.interrupt();
			}
		}
	}
}

建立10條執行緒,當偶數次的時候,中斷該執行緒的執行,打印出該資訊:

明顯看到,就算中斷了,也一樣會執行10條執行緒。說明單單使用這個interrupt()方法是沒有什麼效果的。

栗子二:使用interrupt()配合isInterrupted()方法:

package stop_demo;

public class Interrupt_demo {
	
	
	/**
	 * 例子1:
	 * 只使用interrupt方法
	 * @author fei
	 *
	 */
	public static class Interrupt_demo1 extends Thread{

		@Override
		public void run() {
		      //相對慄一新增對執行緒是否中斷進行判斷
			if (Thread.currentThread().isInterrupted()) {
				System.out.println("執行緒"+Thread.currentThread().getName()+"已被中斷!!");
				return;
			}
			System.out.println("執行緒"+Thread.currentThread().getName()+"在執行~~~~");
			Thread.yield();
		}
	}
	
	public static void main(String[] args) {
		
		//建立10條執行緒
		for (int i = 0; i < 10; i++) {
			Thread thread=new Interrupt_demo1();
			thread.start();
			//如果是偶數,那麼就中斷
			if (i%2==0) {
				thread.interrupt();
			}
		}
		
	}
}

執行後輸出:
在這裡插入圖片描述
可以看到,使用interrupt()配合isInterrupted()方法是可以達到中斷執行緒的目的的,這就理解interrupt()方法設定標誌位的含義了。同時也可以看出,isInterrupted()方法實際上和上一篇文章stopThread()方法類似,但是isInterrupted()更為好用,因為isInterrupted()可以用在迴圈體中,有wait和sleep操作的執行緒中。

栗子三:三個方法配合使用

package stop_demo;

public class Interrupt_demo {
	
	
	/**
	 * 例子1:
	 * 只使用interrupt方法
	 * @author fei
	 *
	 */
	public static class Interrupt_demo1 extends Thread{

		@Override
		public void run() {
			if (Thread.interrupted()) {
				System.out.println("執行緒"+Thread.currentThread().getName()+"判斷為中斷,但已經清除中斷");
				//看是否進入該判斷,如果不進入那麼證明中斷已經清除了
				if (Thread.currentThread().isInterrupted()) {
					System.out.println("執行緒"+Thread.currentThread().getName()+"已被中斷!!");
					return;
				}	
			}
			
			System.out.println("執行緒"+Thread.currentThread().getName()+"在執行~~~~");
			Thread.yield();
		}
	}
	
	public static void main(String[] args) {
		
		//建立10條執行緒
		for (int i = 0; i < 10; i++) {
			Thread thread=new Interrupt_demo1();
			thread.start();
			//如果是偶數,那麼就中斷
			if (i%2==0) {
				thread.interrupt();
			}
		}
		
	}
	
}

執行後輸出:
在這裡插入圖片描述
可以看到,使用靜態方法判斷中斷執行緒,清除後,該執行緒就不是中斷狀態了,所以

if (Thread.currentThread().isInterrupted()) {
					System.out.println("執行緒"+Thread.currentThread().getName()+"已被中斷!!");
					return;
				}	

該方法就不會執行了。