你是否真的弄懂了Java的中斷interrupt?

要弄明白 interrupt,首先要了解如下幾點:java

  1. Java中線程間是協做式,而非搶佔式. 調用一個線程的interrupt() 方法中斷一個線程,並非強行關閉這個線程,只是跟這個線程打個招呼,將線程的中斷標誌位置爲true,線程是否中斷,由線程自己決定。ide

  2. isInterrupted() 斷定當前線程是否處於中斷狀態。spa

  3. 靜態方法 interrupted() 斷定當前線程是否處於中斷狀態,同時中斷標誌位改成 true。線程

  4. 若是方法裏若是拋出中斷異常 InterruptedException,則線程的中斷標誌位會被複位成false,若是確實是須要中斷線程,要求咱們本身在catch語句塊裏再次調用interrupt()。code

  5. Java 中全部的阻塞方法都會拋出 InterruptedExceptionorm

代碼演示1和4

Java中線程間是協做式,而非搶佔式

public class EndThread {
	
	private static class UseThread extends Thread{
		
		public UseThread(String name) {
			super(name);
		}
		
		@Override
		public void run() {
			String threadName = Thread.currentThread().getName();
			while(true) {
				System.out.println(threadName+" is run!");
			}
			//System.out.println(threadName+" interrput flag is "+isInterrupted());
		}
	}

	public static void main(String[] args) throws InterruptedException {
		Thread endThread = new UseThread("endThread");
		endThread.start();
		Thread.sleep(20);
		endThread.interrupt();

	}

}

複製代碼

運行結果:get

endThread is run!
    endThread is run!
    endThread is run!
    endThread is run!
    endThread is run!
    endThread is run!
    endThread is run!
    endThread is run!
    endThread is run!
    endThread is run!
    endThread is run!
    endThread is run!
    endThread is run!
    endThread is run!
    endThread is run!
    ...
複製代碼

endThread 一直在運行,主線程調用 interrupt() 方法並無使 endThread 真正中斷string

public class EndRunnable {
	
	private static class UseRunnable implements Runnable{
		
		@Override
		public void run() {

			String threadName = Thread.currentThread().getName();
			while(Thread.currentThread().isInterrupted()) {
				//若是真發生中斷後,這行代碼不會執行了
				System.out.println(threadName+" is run!");
			}
			System.out.println(threadName+" interrupt flag is " +Thread.currentThread().isInterrupted());
		}			
	}

	public static void main(String[] args) throws InterruptedException {
		UseRunnable useRunnable = new UseRunnable();
		Thread endThread = new Thread(useRunnable,"endThread");
		endThread.start();
		Thread.sleep(20);
		endThread.interrupt();
	}

}
複製代碼

運行結果:it

endThread interrupt flag is false
複製代碼

經過 while(Thread.currentThread().isInterrupted()) 這種方式來控制循環能真正實現 interruptio

由上面兩個例子論證了Java中線程間是協做式,而非搶佔式

若是方法裏若是拋出中斷異常 InterruptedException,則線程的中斷標誌位會被複位成false

public class HasInterruptException {
	
	private static SimpleDateFormat formater 
		= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss_SSS");
	
	private static class UseThread extends Thread{
		
		public UseThread(String name) {
			super(name);
		}
		
		@Override
		public void run() {
			String threadName = Thread.currentThread().getName();
			while(!isInterrupted()) {
				try {
					System.out.println("UseThread:"+formater.format(new Date()));
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					System.out.println(threadName + " catch interrput flag is "
							+ isInterrupted() + " at "
							+ (formater.format(new Date())));
					//方法裏若是拋出InterruptedException,線程的中斷標誌位會被複位成false,
					// 若是確實是須要中斷線程,要求咱們本身在catch語句塊裏再次調用interrupt()。
					interrupt();
					e.printStackTrace();
				}
				System.out.println(threadName);				
			}
			System.out.println(threadName+" interrput flag is " +isInterrupted());
		}
	}

	public static void main(String[] args) throws InterruptedException {
		Thread endThread = new UseThread("HasInterrputEx");
		endThread.start();
		System.out.println("Main:"+formater.format(new Date()));
		Thread.sleep(800);
		System.out.println("Main begin interrupt thread:"+formater.format(new Date()));
		endThread.interrupt();
		

	}

}

複製代碼

運行結果:

UseThread:2019-09-10 15:06:57_995
Main:2019-09-10 15:06:57_995
Main begin interrupt thread:2019-09-10 15:06:58_795
HasInterrputEx catch interrput flag is false at 2019-09-10 15:06:58_795
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at com.xiangxue.ch1.safeend.HasInterrputException$UseThread.run(HasInterrputException.java:28)
HasInterrputEx
HasInterrputEx interrput flag is true複製代碼
相關文章
相關標籤/搜索