你是否真的弄懂了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复制代码
相关文章
相关标签/搜索