一个线程是否能让另一个线程停止运行?除了线程同步互斥机制之外,还有两种方法:
- 可以使用Thread.stop(), Thread.suspend(), Thread.resume()
和Runtime.runFinalizersOnExit() 这些终止线程运行的方法 。但这些方法已经被废弃(The method stop() from the type Thread is deprecated),使用它们是极端不安全的。 - Thread.interrupt() 方法是很好的选择。
public class InterruptDemo {
public static void main(String[] args) throws InterruptedException {
Runnable r = new TestRunnable();
Thread th1 = new Thread(r);
th1.start();
/*三秒后中断线程th1*/
Thread.sleep(3000);
th1.interrupt();
}
}
class TestRunnable implements Runnable {
public void run() {
while (true) {
System.out.println("Thread is running...");
long time = System.currentTimeMillis();// 获取系统时间的毫秒数
while((System.currentTimeMillis() - time < 1000)){
/*程序循环运行1秒钟,不同于sleep(1000)会阻塞进程。*/
}
}
}
}
运行发现,线程th1并没有预期中断。
为什么呢?
每一个线程都有一个属性:中断状态(interrupted status) ,可以通过Thread.currentThread().isInterrupted()
来检查这个布尔型的中断状态。
当调用th1.interrupt()
时,只是改变了线程th1的中断状态。要想真正让线程th1中断,只能是th1自己来实现任务控制。
在上面的程序中,把TestRunnable类中的while (true)修改为while (!Thread.currentThread().isInterrupted())
,程序即可达到我们期望
interrupt无法修改正在阻塞状态(如被Object.wait, Thread.join和Thread.sleep三种方法之一阻塞时)的线程。如果尝试修改,会触发异常:java.lang.InterruptedException
上面的程序把TestRunnable修改成:
class TestRunnable implements Runnable {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("Thread is running...");
long time = System.currentTimeMillis();// 获取系统时间的毫秒数
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.print(e.getMessage());
}
}
}
}
运行几秒便会报错,因为当线程在Thread.sleep时,外部线程尝试调用interrupt()修改它的中断状态(interrupted status) 。
Core Java中有这样一句话:”没有任何语言方面的需求要求一个被中断的程序应该终止。中断一个线程只是为了引起该线程的注意,被中断线程可以决定如何应对中断 “。
换言之,没有任何人可以逼迫美女嫁给自己,告诉她“我要娶你”是你的事,至于嫁不嫁最终由她决定。