Java中使用interrupt通知线程停止详析
概述
在Java多线程编程中,有时候需要在某个条件满足时中断线程的执行。Java中提供了一种机制,即通过中断(interrupt)的方式通知线程停止。本文将详细阐述Java中使用interrupt通知线程停止的完整攻略。
了解中断机制
在Java中,线程有一个boolean类型的中断标记,初始值为false。当线程调用了interrupt()方法时,中断标记就会被设置为true,表示该线程收到了中断信号。线程在被中断时,可以通过isInterrupted()方法检查中断标记是否被设置了。
如何停止线程
有两种方式停止线程,分别是:
-
使用中断(interrupt)机制
在线程中处理中断信号,以此来停止线程。比如,在线程中不断地检查中断标记,一旦中断标记为true,就立即结束线程。
-
使用共享变量
在线程外部设置一个共享变量,在满足某个条件时,将变量值设置为true。线程在执行时不断检查共享变量的值,如果发现变量值为true,就立即结束线程。
如何使用中断机制停止线程
1. 在线程中检测中断标记
在线程中处理中断信号最常见的方式是不断地检查中断标记,一旦标记为true,就立即结束线程。
public class MyThread extends Thread {
public void run() {
while(!isInterrupted()) {
// do something
}
}
}
上面的代码中,线程不断地执行某个任务,同时在每次循环开始时检查中断标记,如果标记为true,则立即退出线程。如果不检查中断标记,那么线程将不会被停止。
2. 在sleep、wait等阻塞方法中捕获中断异常
在使用阻塞方法(如sleep、wait等)时,也可以使用中断机制停止线程。当线程处于sleep、wait等阻塞状态时,调用线程的interrupt()方法将会导致线程抛出InterruptedException异常,从而使线程提前退出阻塞状态。
public class MyThread extends Thread {
public void run() {
try {
while(!isInterrupted()) {
// do something
Thread.sleep(1000); // 使用阻塞方法
}
} catch (InterruptedException e) {
// 处理中断异常
}
}
}
上面的代码中,线程在循环过程中使用了sleep阻塞方法。由于线程处于阻塞状态,无法在循环中检查中断标记。因此,当线程收到中断信号时,会抛出InterruptedException异常,从而使线程提前退出阻塞状态,进而继续执行线程中的循环所在位置的代码。需要注意的是,抛出InterruptedException异常也清除线程的中断状态。
示例说明
示例一
public class ThreadInterruptDemo {
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("线程正在运行...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
break;
}
}
System.out.println("线程结束");
}
});
t.start();
Thread.sleep(5000);
t.interrupt();
}
}
上述示例中,主线程创建了一个新线程t,并启动该线程。在新线程t中使用while循环不断输出一行“线程正在运行…”,并使用Thread.sleep()方法暂停1秒钟,从而模拟线程正在工作。
在主线程休眠5秒钟后,调用新线程t的interrupt()方法,线程t会收到中断信号,终止循环并输出“线程结束”。这说明通过使用中断机制,能够实现对线程的安全停止。
示例二
public class ThreadInterrupt2Demo {
public static void main(String[] args) throws InterruptedException {
ThreadCounter counter = new ThreadCounter();
Thread t1 = new Thread(counter, "Thread-1");
Thread t2 = new Thread(counter, "Thread-2");
t1.start();
t2.start();
Thread.sleep(5000);
t1.interrupt();
t2.interrupt();
}
private static class ThreadCounter implements Runnable {
@Override
public void run() {
int count = 0;
while (!Thread.currentThread().isInterrupted() && count < 5) {
count++;
System.out.println(Thread.currentThread().getName() + ": " + count);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // 重新设置中断标志
}
}
System.out.println(Thread.currentThread().getName() + "结束");
}
}
}
上述示例中,主线程创建了两个新线程t1和t2,并启动这两个线程。线程t1和t2都执行一个Runnable接口实现类ThreadCounter的代码逻辑,主要是在循环中不断输出线程名称和计数器的数值,并使用Thread.sleep()方法暂停1秒钟,从而模拟线程正在工作,计数器的默认初始值为0。
在主线程休眠5秒钟后,调用线程t1和t2的interrupt()方法,线程t1和t2将会收到中断信号,并尝试重新设置自己的中断标记,从而安全终止循环输出线程结束信息。
需要注意的是,由于在线程t1和t2中捕获InterruptedException异常而重新设置中断标记,因此在重新设置中断标记后,循环中使用Thread.sleep()方法时就可能再次触发InterruptedException异常,所以需要再次调用interrupt()方法来设置自己的中断标记。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java中使用interrupt通知线程停止详析 - Python技术站