中断一个线程

有多个执行线程的 Java 程序只在所有线程执行结束后才结束(更明确地说, 是当所有非守护线程执行结束或其中一个线程调用了System.exit()方法). 有时需要主动结束一个线程, 如希望结束一个程序或用户想取消线程在做的任务时.

Java提供了中断机制以告知一个线程我们想结束它了。此机制的一个特质是线程必须检查它是否被中断并能决定是否响应析构请求。线程可以忽略并继续执行。

任务

创建一个线程生成质数,在 5 秒后使用中断机制强制析构。

实现

  • 线程类 (PrimeGenerator): 生成并打印质数

    • 覆盖 run() 方法,在其中从1开始逐个判断是否质数
    @Override
    public void run() {
        long number = 1L;
        while (true) {
            if (isPrime(number)) {
                System.out.printf("Number %d is Prime\n", number);
            }
            // 判断是否中断 (见后述代码段)
            number++;
        }
    }
    
    • 判断是否中断
            if (isInterrupted()) {
                System.out.printf("The Prime Generator has been Interrupted\n");
                return;
            }
    
    • 判断是否为质数
    private boolean isPrime(long number) {
        if (number <= 2) {
            return true;
        }
        for (long i = 2; i < number; i++) {
            if ((number % i) == 0) {
                return false;
            }
        }
        return true;
    }
    
  • 控制类 (Main)

    • 创建并启动一 PrimeGenerator 类对象
    Thread task = new PrimeGenerator();
    task.start();
    
    • 等待5秒后中断
    try {
        Thread.sleep(5000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    task.interrupt();
    

工作原理

Thread 类有个属性保存一个布尔值, 表示线程是否被中断。当调用线程的 interrupt() 方法,将设置此属性值为 true。 isInterrupted() 方法只返回该属性值。

了解更多

  • Thread 的 interrupted() 静态方法也可以用来检查线程是否被中断, 它检查当前正在执行的线程是否被中断。
    isInterrupted() vs. Thread.interrupted()

    • isInterrupted() : 不改变 interrupted 属性的值。建议使用。
    • Thread.interrupted() : 设置 interrupted 属性值为 false
  • 线程可忽略中断,但不建议这样做