发布时间:2023-02-12 文章分类:编程知识 投稿人:李佳 字号: 默认 | | 超大 打印

Java线程里:“中断”就是指“终止”,与操作系统里的"中断"、“异常”是完全不同的概念;
由于stop()方法过于暴力,可能导致资源回收无法风险、开销过大等问题,此方法已过期,故Java中没有强制中断线程的手段;但可以调用interupt()、interupted()方法来向进程提出中断请求,待进程自行处理,这是一种更优雅的中断方式。

注意:当需要中断线程时,最佳实践就是利用线程的中断位,而不是自定义中断状态,因为当线程被阻塞时,原生中断位仍然会被监听,而自定义的则不能。

以下两类场景会应用到线程中断:

  1. 不在线程内部检测中断位并手动响应中断,线程将无限执行下去:
public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (true) {
                System.err.println("子线程");
            }
        });
        thread.start();
        System.out.println("---" + thread.isInterrupted());  // ---false
        /**
         * 这主线程只是改变了子线程的中断位改为了true
         * 由于子线内部并没有就中断位进行检测和处理,故子线程并不会终止,会无限打印下去
         */
        thread.interrupt();
        TimeUnit.SECONDS.sleep(1);
        System.err.println("===" + thread.isInterrupted());  // ===true
    }
  1. 在非阻塞线程内部手动响应中断:
public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                System.out.println(Thread.currentThread().isInterrupted());
                System.err.println("子线程");
            }
        });
        thread.start();
        System.out.println("---" + thread.isInterrupted());  // ---false
        /**
         * 这主线程只是改变了子线程的中断位改为了true
         */
        TimeUnit.SECONDS.sleep(3);
        thread.interrupt();
        System.err.println("===" + thread.isInterrupted());  // ===true
    }
  1. 在非阻塞线程内部手动响应中断:
/**
 * 当子线程需要响应主线程的中断请求,而停止时。可以通过在子线程中实时检测其自身的中断状态来达到停止的目的
 *
 * @param args
 */
public static void main(String[] args) throws InterruptedException {
    Thread thread = new Thread(() -> {
        // 实时检测自身中断状态
        while (!Thread.currentThread().isInterrupted()) {
            System.err.println("子线程");
        }
    });
    thread.start();
    TimeUnit.SECONDS.sleep(2);
    // 修改子线程的中断状态
    thread.interrupt();
}
  1. 中断阻塞中的线程:
public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    TimeUnit.SECONDS.sleep(5);
                } catch (InterruptedException e) {
                    // 异常被捕获后,阻塞被打破、中断位被设为false,所以异常中永远输出false
                    System.out.println("2 ----" + Thread.currentThread().isInterrupted());  // 2 ----false
                  	System.err.println("回收资源");
                    e.printStackTrace();
                }
                System.err.println("子线程逻辑");
            }
        });
        thread.start();
        TimeUnit.SECONDS.sleep(1);
        thread.interrupt();
        System.out.println(thread.isInterrupted());  // true
        TimeUnit.SECONDS.sleep(5);
    }
  1. 优雅中断非阻塞线程:
public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while (true) {
                if (Thread.interrupted()) {
                    System.out.println("清理资源");
                    break;
                }
                System.err.println("子线程逻辑");
            }
        });
        thread.start();
        TimeUnit.SECONDS.sleep(1);
        thread.interrupt();
    }