Java线程停止的正确方式

Java线程停止以前的做法是通过Thread.stop() 的方式来停止具体的线程,但是这个方法目前是被废弃掉的,不推荐使用. 具体原因:

1、该方式是通过立即抛出ThreadDeath异常来达到停止线程的目的,而且此异常抛出可能发生在程序的任何一个地方,包括catch、finally等语句块中。

2、由于抛出ThreadDeatch异常,会导致该线程释放所持有的所有的锁,而且这种释放的时间点是不可控制的,可能会导致出现线程安全问题和数据不一致情况,比如在同步代码块中在执行数据更新操作时线程被突然停止。

因此,为了避免Thread.stop()带来的问题,推荐使用被称作为Interrupt(中断)的协作机制来停止一个正在运行的线程。Interrupt 方法,只是改变中断状态, 没有实际终止线程.

在JVM中,每个线程都有一个与之关联的Boolean属性,被称之为中断状态,可以通过Thread.currentThread().isInterrupted()来获取当前线程的中断状态,初始值为false。中断状态仅仅是线程的一个属性,用以表明该线程是否被中断。因为中断是线程之间的一种协作机制,因此对于被中断的线程而言,可以对中断做出响应,也可以不做任何响应.

在Java中,有些方法已经实现了对中断的响应处理,比如Thread.sleep()、Object.wait()、BlockingQueue.put()、BlockingQueue.take()等等。当线程执行正在这些方法时,被其他线程中断掉,该线程会首先清除掉中断状态(设置中断属性为false),然后抛出InterruptedException异常。

@Override
  public void run() {
    final Thread currentThread = Thread.currentThread();
    for (; ; ) {
      try {
        //空队列判断
        if (isEmpty()) {
          log.info("DelayedQueue Is Empty");
          synchronized (currentThread) {
            currentThread.wait();
          }
          continue;
        }
      } catch (InterruptedException e) {
        //上传中断状态
        currentThread.interrupt();
        log.error(e.getMessage(), e);
      }
    }

在平时代码中对中断的处理,不推荐生吞中,最好的做法就是上传中断状态,保留中断发生的证据,以便调用栈中更高层的代码能够知道发生了中断,并对中断做出响应。

然而上传中断状态, 并不能让for(;;)循环终止, 需要在开头添加如下的判断代码:

@Override
  public void run() {
    final Thread currentThread = Thread.currentThread();
    for (; ; ) {
      //判断线程状态: 如果是中断, 则抛出异常终止, 或者直接return
      if (currentThread.isInterrupted()) {
        throw new RuntimeException("Thread Has Been Stoped");
      }
      try {
        //空队列判断
        if (isEmpty()) {
          log.info("DelayedQueue Is Empty");
          synchronized (currentThread) {
            currentThread.wait();
          }
          continue;
        }
      } catch (InterruptedException e) {
        //上传中断状态
        currentThread.interrupt();
        log.error(e.getMessage(), e);
      }
    }

这样, 当其他地方调用thread.interrupt()方法时, 该线程才能被正常的终止.

参考链接:https://blog.csdn.net/trackle400/article/details/81775189

发表评论

电子邮件地址不会被公开。 必填项已用*标注