Thread.currentThread().interrupt()
该方法为非静态方法,该方法的作用:标记线程为中断状态,仅仅是标记
/** * @author chaird * @create 2020-12-22 13:58 */ public class Main { public static void main(String[] args) { // 获取当前线程 Thread currentThread = Thread.currentThread(); // 获取当前线程的中断状态 System.out.println(currentThread.isInterrupted()); // false // 标记为中断线程 currentThread.interrupt(); // 获取当前线程的中断状态 System.out.println(currentThread.isInterrupted()); // true } }
Thread.currentThread().isInterrupted()
该方法为非静态方法,该方法的作用:返回线程的中断状态
/** * @author chaird * @create 2020-12-22 13:58 */ public class Main { public static void main(String[] args) { // 获取当前线程 Thread currentThread = Thread.currentThread(); // 获取当前线程的中断状态 System.out.println(currentThread.isInterrupted()); // false // 标记为中断线程 currentThread.interrupt(); // 获取当前线程的中断状态 System.out.println(currentThread.isInterrupted()); // false } }
Thread.interrupted()
/** * @author chaird * @create 2020-12-22 13:58 */ public class Main { public static void main(String[] args) { // 获取当前线程 Thread currentThread = Thread.currentThread(); // 获取当前线程的中断状态 System.out.println(currentThread.isInterrupted()); // false // 标记为中断线程 currentThread.interrupt(); // 获取当前线程的中断状态 System.out.println(currentThread.isInterrupted()); // false // (1)获取当前线程的中断状态,(2)并且取消中断状态 boolean interrupted = Thread.interrupted(); System.out.println(interrupted); // true System.out.println(currentThread.isInterrupted()); // false 。因为Thread.interrupted()中取消中断状态 } }
如何正确的中断一个正在执行的线程
案例1:没有坑并且不带Sleep的代码
import java.time.LocalDateTime; /** * @author chaird * @create 2020-12-22 14:15 */ public class Start { public static void main(String[] args) { InterruptedTask interruptedTask = new InterruptedTask(); Thread interruptedThread = new Thread(interruptedTask); interruptedThread.start(); try { // 睡1秒 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // 设置线程为中断状态 interruptedThread.interrupt(); } } class InterruptedTask implements Runnable { @Override public void run() { Thread currentThread = Thread.currentThread(); while (true) { if (currentThread.isInterrupted()) { break; } System.out.println("LocalDateTime:" + LocalDateTime.now().toString()); } } }
案例2:有坑并且带Sleep的代码
下述代码明明调用了线程的interrupt()方法来中断线程,但是却并没有起到啥作用。原因是线程的run()方法在执行的时候,大部分时间都是阻塞在sleep(100)上,当其他线程通过调用执行线程的interrupt()方法来中断执行线程时,大概率的会触发InterruptedException异常,在触发InterruptedException异常的同时,JVM会同时把线程的中断标志位清除,所以,这个时候在run()方法中判断的currentThread.isInterrupted()会返回false,也就不会退出当前while循环了。
import java.time.LocalDateTime; /** * @author chaird * @create 2020-12-22 14:15 */ public class Start { public static void main(String[] args) { InterruptedTask interruptedTask = new InterruptedTask(); Thread interruptedThread = new Thread(interruptedTask); interruptedThread.start(); try { // 睡1秒 Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } // 设置线程为中断状态 interruptedThread.interrupt(); } } class InterruptedTask implements Runnable { @Override public void run() { Thread currentThread = Thread.currentThread(); while (true) { if (currentThread.isInterrupted()) { break; } System.out.println("LocalDateTime:" + LocalDateTime.now().toString()); try { // 睡0.1秒 Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } }
解决办法
import java.time.LocalDateTime; /** * @author chaird * @create 2020-12-22 14:15 */ public class Start { public static void main(String[] args) { InterruptedTask interruptedTask = new InterruptedTask(); Thread interruptedThread = new Thread(interruptedTask); interruptedThread.start(); try { // 睡1秒 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // 设置线程为中断状态 interruptedThread.interrupt(); } } class InterruptedTask implements Runnable { @Override public void run() { Thread currentThread = Thread.currentThread(); while (true) { if (currentThread.isInterrupted()) { break; } System.out.println("LocalDateTime:" + LocalDateTime.now().toString()); try { // 睡0.1秒 Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); // 在触发InterruptedException异常的同时,JVM会同时把线程的中断标志位清除,所以需要复现中断状态 currentThread.interrupt(); } } } }
案例3:有坑,需要JMM知识解决
主线程睡0.5秒,然后去中断interruptedThread线程,但是运行下面的代码线程并没有结束,说明有BUG
/** * @author chaird * @create 2020-12-22 14:15 */ public class Start { public static void main(String[] args) { InterruptedTask interruptedTask = new InterruptedTask(); Thread interruptedThread = new Thread(interruptedTask); interruptedThread.start(); try { // 睡0.5秒 Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } interruptedTask.myInterrupted(); } } class InterruptedTask implements Runnable { private boolean sign = false; @Override public void run() { Thread currentThread = Thread.currentThread(); while (!sign) {} } public void myInterrupted() { sign = true; } }
解决办法
因为InterruptedTask里的while(true)太快了,没有任何逻辑,所以一个字:快。
虽然JMM中主内存中的更新了数据,但是本地内存来不及去主内存中更新数据,所以上面的案例中InterruptedTask里的sign一直都是false。volatile可以解决内存可见性。这就是另一个知识点了,不多解释。
把 private boolean sign = false 改为 private volatile boolean sign = false;
注意
本文中说的中断状态其实就是一个标志位,而不是真正的中断线程。
class MyThread { // 中断状态标志位 private volatile boolean sign = false; }