当前位置: 代码迷 >> 综合 >> 线程的两阶段终止模式(中断)
  详细解决方案

线程的两阶段终止模式(中断)

热度:45   发布时间:2024-03-10 01:50:10.0

Java 中线程的生命周期

Java 语言中线程共有六种状态,分别是:
1、NEW(初始化状态)
2、RUNNABLE(可运行 / 运行状态)
3、BLOCKED(阻塞状态)
4、WAITING(无时限等待)
5、TIMED_WAITING(有时限等待)
6、TERMINATED(终止状态)
他们之间的关系转换如以下状态转换图:
在这里插入图片描述

TERMINATED(终止状态)

今天主要讲线程如何从Runnable状态如何变为终止状态。

  • 第一种:
    线程的任务执行完了,就进入了terminated状态。(这个好理解,我们new Thread(Runnable runnable), runnable中的任务执行完了,线程就终止了。如果是线程池的话就是将线程归还给线程池了)
  • 第二种
    Thread.stop()方法。 野蛮粗暴的终止线程,但这种方式是不推荐的,该方式使得JVM强制终止该线程,释放该线程持有的所有的锁,可能会破坏其他线程的执行状态。
  • 第三种(官方推荐)
    中断标记
    在Thread.stop()方法过时说明中,有这样一段:
Many uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running.  The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running.  If the target thread waits for long periods (on a condition variable, for example), the interrupt method should be used to interrupt the wait.

它的意思是说:许多使用stop方法的地方应该改成 一些标识线程需要停止的状态变量的形式,需要停止的线程去轮询这个标志位来决定是否终止线程。这里说的标志位就可以用中断标记实现。

应该怎么使用中断标记

先看以下示例:

/*** <pre>类名: InterruptTest</pre>* <pre>描述: 中断测试</pre>* <pre>版权: web_chen@163.com</pre>* <pre>日期: 2020/10/30 8:19</pre>* <pre>作者: chenwb</pre>*/
public class InterruptTest {
    private Thread sleepThread;/*** @Description 创建一个循环执行的线程* @author chenwb* @date 2020/10/30 9:01*/synchronized void start() {
    sleepThread = new Thread(() -> {
    // 根据中断标志为判断是否继续执行while (!Thread.currentThread().isInterrupted()) {
    System.out.println("sleepThread start!");try {
    Thread.sleep(3000);} catch (InterruptedException e) {
    System.out.println("sleepThread has been interrupted");// 重置中断标志Thread.currentThread().interrupt();}System.out.println("sleepThread end!");}});sleepThread.start();}/*** @Description 终止线程的方法stop* @author chenwb* @date 2020/10/30 9:01*/synchronized void stop() {
    sleepThread.interrupt();}public static void main(String[] args) throws InterruptedException {
    InterruptTest interruptTest = new InterruptTest();// 启动线程interruptTest.start();// 让线程执行5sThread.sleep(5000);// 终止线程interruptTest.stop();}
}

执行结果:

sleepThread start!
sleepThread end!
sleepThread start!
sleepThread has been interrupted
sleepThread end!

小结:

  • 设置中断标志:Thread.interrupt(),设置中断标记
  • 判断是否有中断标记:
// 判断完之后会清除中断标记
public static boolean interrupted() {
    return currentThread().isInterrupted(true);
}
// 判断完之后不会清除中断标记
public boolean isInterrupted() {
    return isInterrupted(false);
}
  • 要注意的点是:
    上面例子中Thread.sleep捕获了InterruptedException 异常之后要重新设置中断标志,原因是Thread.sleep,Object.wait方法在收到中断时会抛出中断异常,同时清除标志位,如果不重新设置,就会在后续判断中失效

所以在类似判断中断标志的逻辑中,尽量避免调用第三方的库,因为你不知道第三方的代码是否在Thread.sleep,Object.wait抛出中断异常之后重新设置了标志位

  相关解决方案