欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

中断(interrupted()、isInterrupted())、Executor的中断

发布时间:2024/10/14 编程问答 53 豆豆
生活随笔 收集整理的这篇文章主要介绍了 中断(interrupted()、isInterrupted())、Executor的中断 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

1. 中断

一个线程执行完毕之后会自动结束,如果在运行过程中发生异常也会提前结束。

InterruptedException通过调用一个线程的 interrupt() 来中断该线程,如果该线程处于阻塞、限期等待或者无限期等待状态,那么就会抛出 InterruptedException,从而提前结束该线程。

但是不能中断 I/O 阻塞和 synchronized 锁阻塞。

对于以下代码,在 main() 中启动一个线程之后再中断它,由于线程中调用了Thread.sleep() 方法,因此会抛出一个InterruptedException,从而提前结束线程,不执行之后的语句。

public class InterruptExample {private static class MyThread1 extends Thread {@Overridepublic void run() {try {Thread.sleep(2000);System.out.println("Thread run");} catch (InterruptedException e) {e.printStackTrace();}}} } public static void main(String[] args) throws InterruptedException {Thread thread1 = new MyThread1();thread1.start();thread1.interrupt();System.out.println("Main run"); }

结果:

1.1 interrupted()

如果一个线程的 run() 方法执行一个无限循环,并且没有执行 sleep() 等会抛出InterruptedException 的操作,那么调用线程的 interrupt() 方法就无法使线程提前结束。

由于调用 interrupt() 方法会设置线程的中断标记,此时调用 interrupted() 方法会返回 true。因此可以在循环体中使用 interrupted() 方法来判断线程是否处于中断状态,从而提前结束线程。

public class InterruptExample {private static class MyThread2 extends Thread {@Overridepublic void run() {while (!interrupted()) {// ..} System.out.println("Thread end");}} } public static void main(String[] args) throws InterruptedException {Thread thread2 = new MyThread2();thread2.start();thread2.interrupt(); }

1.1.1 interrupted()源码(原博)

interrupted()是静态方法:内部实现是调用的当前线程的isInterrupted(),并且会重置当前线程的中断状态。

1.1.2 isInterrupted()源码

 isInterrupted()是实例方法,是调用该方法的对象所表示的那个线程的isInterrupted(),不会重置当前线程的中断状态

1.1.3 测试对比

第一个红框中断的线程是我们自己创建的myThread线程,我调用的interrupted(),由上面源码可知是判断当前线程的中断状态,当前线程是main线程,我根本没有中断过main线程,所以2次调用均返回“false”

第一个红框中断的线程是当前线程(main线程),我调用的interrupted(),由上面源码可知是判断当前线程的中断状态,当前线程是main线程,所以第1次调用结果返回“true”,因为我确实中断了main线程;

由源码可知interrupted()调用的是isInterrupted(),并会重置中断状态,所以第一次调用之后把中断状态给重置了,从中断状态重置为非中断状态,所以第2次调用的结果返回“false”。

第一个红框中断的线程是我们自己创建的myThread线程,我调用的isInterrupted(),由上面源码可知是判断执行该方法的对象所表示线程的中断状态,也就是myThread引用所表示的线程的中断状态,所以第1次调用结果返回“true”;

由源码可知isInterrupted()不会重置中断状态,所以第一次调用之后没有把中断状态给重置(从中断状态重置为非中断状态),所以第2次调用的结果还返回“true”。

第一个红框中断的线程是我们自己创建的myThread线程,我调用的isInterrupted(),由上面源码可知是判断执行该方法的对象所表示线程的中断状态,也就是main的中断状态,我压根没有中断main线程,所以理所当然2次调用结果都返回“false”。

第一个红框中断的线程是当前线程(main线程),我调用的isInterrupted(),由上面源码可知是判断执行该方法的对象所表示线程的中断状态,也就是main的中断状态,所以第1次调用结果返回“true”;

因为源码内部调用isInterrupted() 参数传的false,不会重置main线程的中断状态,所以第2次调用还是返回”true”。

2. Executor 的中断操作

调用 Executor 的 shutdown() 方法会等待线程都执行完毕之后再关闭;

但是如果调用的是 shutdownNow() 方法,则相当于调用每个线程的 interrupt() 方法。

2.1 举例

以下使用 Lambda 创建线程,相当于创建了一个匿名内部线程。

public static void main(String[] args) {ExecutorService executorService = Executors.newCachedThreadPool();executorService.execute(() -> {try {Thread.sleep(2000);System.out.println("Thread run");} catch (InterruptedException e) {e.printStackTrace();}});executorService.shutdownNow();System.out.println("Main run"); }

2.2 如果只想中断 Executor 中的一个线程

可以通过使用 submit() 方法来提交一个线程,它会返回一个 Future<?> 对象,通过调用该对象的 cancel(true) 方法就可以中断线程。

Future<?> future = executorService.submit(() -> {// .. }); future.cancel(true);

 

总结

以上是生活随笔为你收集整理的中断(interrupted()、isInterrupted())、Executor的中断的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。