线程停止
Java中的线程不能强行停止。需要让一个线程停止时,我们应该调用线程对象的interrupt()
方法,向其发送中断信号,线程则会判断是否收到这个信号,如果收到就退出。线程退出可以直接return
,也可以手动抛出InterruptedException
,这个异常是一个受检查异常。
注:虽然JDK提供了stop()
方法强行停止线程,但是该方法已经Deprecated,并且十分不推荐使用。
isInterrupted()和interrupted()
实际上判断线程是否收到interrupted信号有两个方法:
isInterrupted():线程实例的方法,只判断一个线程对象是否具有线程中断信号,返回布尔值。
interrupted():静态方法,判断当前线程是否具有线程中断信号,如果有就清除中断信号,返回清除之前的判断结果布尔值。
我们具体开发时,可以根据实际需要进行选择。
线程停止例子
使用return实现线程停止
MyThread1.java
package com.gacfox.demo;
public class MyThread1 implements Runnable {
@Override
public void run() {
while (true) {
if (Thread.currentThread().isInterrupted()) {
System.out.println("thread 1 收到interrupt信号,线程退出");
return;
}
}
}
}
上述代码中,通过isInterrupted()
函数判断当前线程是否收到中断线程的信号,收到直接函数返回,以此停止线程。
使用异常实现线程停止
MyThread2.java
package com.gacfox.demo;
public class MyThread2 implements Runnable {
@Override
public void run() {
try {
while (true) {
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
}
} catch (InterruptedException e) {
System.out.println("thread 2 捕获异常,线程停止");
e.printStackTrace();
}
}
}
上面代码中,收到线程停止的信号,会手动抛出InterruptedException
,被catch抓到即会退出子线程执行流程。
运行结果
Main.java
package com.gacfox.demo;
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new MyThread1());
Thread t2 = new Thread(new MyThread2());
t1.start();
t2.start();
Thread.sleep(500);
t1.interrupt();
t2.interrupt();
}
}
这里我们同时启动了上述两个线程,然后500ms后,同时结束。
对于睡眠线程的处理
处于睡眠状态的线程,怎样判断线程中断信号呢?实际上sleep()
函数已经把这个判断实现了,处于睡眠过程中的线程,如果收到线程中断信号,sleep()
会主动抛出InterruptedException
,我们使用sleep()
的时候,也是强制try...catch...
的。
线程停止最佳实践
停止一个线程,最推荐的做法是抛出InterruptedException
。相对于return
的方式,使用异常能够在catch
中继续向上抛出异常,使得线程停止事件能够向上传播。
另外,不要使用stop()
停止线程!