多线程并发编程系列教程

3 Terminal of Thread(线程终止)

2019-11-02  本文已影响0人  Vander1991

3.1 线程终止简介

线程终止顾明思议,我们在线程运行期间,有时候需要在某些条件下,让线程停止运行,并且目标线程只有在被阻塞(此处的阻塞不是指线程的BLOCKED状态)的情况下才能被终止。
有以下两种:
1、如果目标线程在调用Object.wait(long)、Object.wait(long, int)、join()、join(long, int)、sleep(long, int)方法被阻塞,那么interrupt会生效,该线程的中断状态将被清除,抛出InterruptedException异常。
2、如果目标线程是被I/O或者NIO中的Channel所阻塞,同样,I/O操作会被中断或者返回特殊异常值。达到终止线程的目的。
让线程中断的方式就是使用thread.Interrupt或者使用标志位。

3.1.1 方式一:使用Interrupt终止线程

StopThread.java:

public class StopThread extends Thread {
    private int i = 0, j = 0;

    @Override
    public void run() {
        synchronized (this) {
            // 增加同步锁,确保线程安全
            ++i;
            try {
                // 休眠10秒,模拟耗时操作
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            ++j;
        }
    }

    public void print() {
        System.out.println("i=" + i + " j=" + j);
    }

}

InterruptThread.java:

public class InterruptThread {

    public static void main(String[] args) throws InterruptedException {
        StopThread thread = new StopThread();
        thread.start();
        // 休眠1秒,确保i变量自增成功
        Thread.sleep(1000);
        // 暂停线程
        //  thread.stop(); // 错误的终止
        thread.interrupt(); // 正确终止
        while (thread.isAlive()) {
            // 确保线程已经终止
        } // 输出结果
        thread.print();
    }

}

运行结果:可以观察到挂住1秒之后就出结果了,说明线程被中断成功了


运行结果

线程在接收到Interrupt指令的时候,会抛出异常,这样也能让你的应用程序在finally中进行一些资源的回收关闭等操作。

3.1.2 方式二:使用标志位终止线程

/** 通过状态位来判断 */
public class FlagInterruptThread extends Thread {
  public volatile static boolean flag = true;

  public static void main(String[] args) throws InterruptedException {
    new Thread(() -> {
      try {
        while (flag) { // 判断是否运行
          System.out.println("运行中");
          Thread.sleep(1000L);
        }
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }).start();
    // 3秒之后,将状态标志改为False,代表不继续运行
    Thread.sleep(3000L);
    flag = false;
    System.out.println("程序运行结束");
  }
}

运行结果:


运行结果

3.2 错误的线程终止

在早期的JDK中,还有使用Stop来进行线程终止,使用Stop来进行线程终止最大的问题就是造成了线程的不安全性,就拿上面这段代码为例,Stop会在线程处于wait状态的时候,接收到Stop指令就直接把线程干掉了,本来上面的那段代码里面用了关键字synchronized来保证线程的安全性,线程直接被终止了就会导致i++了但是j却还没有进行加1操作。这里值得一提的是,如果用stop来终止线程,但是你代码里面有finally的语句块,finally的语句块还是会执行的。(目前不用Stop来终止线程,所以这也不用太关心)。

上一篇 下一篇

猜你喜欢

热点阅读