前言
当提及如何终止一个线程时,部分读者通常立马想到的方法肯定是stop(),但是stop()方法并不被推荐使用(很多规范中是禁止使用的),其原因是强制终止一个线程,会导致程序不正常的结束,会出现资源未正确释放、程序结果不正确等等问题。而是否终止一个线程应该把这个控制权转交给当前被终止的线程本身,此时采用的办法就是** **interrupt()方法来终止,该方法相当于修改一个共享变量的值,当运行中的线程判断当前值为false则继续运行,如果有地方调用当前thread的interrupt()方法,那么这个值将变为true,此时当前线程可以根据这个值的修改来正确的终止线程的运行。
API
在java.lang.Thread中主要提供了如下与线程中断相关的方法,其具体方法名与主要作用如下表所示。
interrupted()和isInterrupted()区别
看了上述API讲述和Thread中的源码,已经清楚interrupted()和isInterrupted()的主要区别了
interrupted()为静态方法,isInterrupted()为普通方法
interrupted() 返回中断标志且清除(恢复)中断标志,isInterrupted()仅返回中断标志
使用方法
我们先验证中断异常响应,通过如下两种方法的使用示例来介绍,注意Runner中的run方法的部分区别
方法一
方法二
package com.liziba.p7; import java.util.concurrent.TimeUnit; /** * <p> * * </p> * * @Author: Liziba * @Date: 2021/6/24 21:18 */ public class ThreadInterruptedDemo { public static void main(String[] args) throws InterruptedException { Thread t1 = new Thread(new Runner(), "Thread-01"); t1.start(); // 主线程睡眠2秒,保证t1的充分执行 TimeUnit.SECONDS.sleep(1); // 发起中断 t1.interrupt(); } static class Runner implements Runnable { @Override public void run() { while (!Thread.currentThread().isInterrupted()) { System.out.println(Thread.currentThread().getName() + " is running ."); try { // 睡眠2秒,保证主线程发起的中断能被捕获 TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { // 不对中断做任何处理,try住异常,打印 e.printStackTrace(); } } } } }
接下来我们来验证interrupted()对于中断的标志的清除
package com.liziba.p7; import java.util.concurrent.TimeUnit; /** * <p> * isInterrupted() * </p> * * @Author: Liziba * @Date: 2021/6/24 21:20 */ public class ThreadInterruptDemo2 { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new Runner(), "Thread-1"); thread.start(); TimeUnit.SECONDS.sleep(2); thread.interrupt(); } static class Runner implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() +" interrupted flag is " + Thread.currentThread().isInterrupted()); while (!Thread.currentThread().isInterrupted()) { try { System.out.println(Thread.currentThread().getName() + " is running ."); TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { // 响应中断,抛出异常后中断位置会被复位,自己中断自己 Thread.currentThread().interrupt(); // 这里调用isInterrupted()获取当前的中断标志 System.out.println(Thread.currentThread().getName() +" interrupted flag is " + Thread.currentThread().isInterrupted()); } } } } }
将上述catch中的Thread.currentThread().isInterrupted()修改为Thread.interrupted()再次运行
package com.liziba.p7; import java.util.concurrent.TimeUnit; /** * <p> * * </p> * * @Author: Liziba * @Date: 2021/6/24 21:23 */ public class ThreadInterruptDemo2 { public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(new Runner(), "Thread-1"); thread.start(); TimeUnit.SECONDS.sleep(2); thread.interrupt(); } // 区别在catch中 static class Runner implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() +" interrupted flag is " + Thread.currentThread().isInterrupted()); while (!Thread.currentThread().isInterrupted()) { try { System.out.println(Thread.currentThread().getName() + " is running ."); TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { // 响应中断,抛出异常后中断位置会被复位,自己中断自己 Thread.currentThread().interrupt(); // 注意区别在这里 System.out.println(Thread.currentThread().getName() +" interrupted flag is " + Thread.interrupted()); } } } } }