(二)java 线程运行暂停、停止

在开始本文之前,需要了解线程的状态,分别是:

//更详细的解释可以见源码 Thread.class 中的 State
public enum State{
        NEW,//新建状态
        RUNNABLE,//运行状态
        BLOCKED,//阻塞状态
        WAITING,//等待状态
        TIMED_WAITING,//有时间限制的等待状态
        TERMINATED;//终止状态
        }

线程暂停、中断

1.线程如何中断?
  1. 使用 interrupt() 中断,给线程设置一个中断标志,本地方法
    interrupt0();// Just to set the interrupt flag
    然后可以通过方法 isInterrupted()interrupted() 查询线程的是否被中断而进行其他的操作。
  2. 如果线程处于 BLOCKED WAITING TIMED_WAITING 状态时,则会触发中断异常 InterruptedException ,并且中断标志位会被清除,如果是锁状态 BLOCKED 并且在做 IO 操作,则触发 ClosedByInterruptException 异常,同样我们可以在捕获异常中做所谓的暂停操作或其他。
  3. 在其他状态中,仅仅是设置中断标志位,不抛异常。

需注意的是,查询中断状态的方法中 isInterrupted() 不会重置中断标志位,而 interrupted() 会重置中断标志位。如果想保持线程的中断标志不改变,调用 isInterrupted() 即可,或者调用 interrupted() 后再次调用中断 interrupt(),但线程运行中不能保证时间上的连续性,有可能导致其他地方查询线程中断情况时,线程中断标志已被重置而出现其他的问题。

2.当线程启动后,只有运行态,即 RUNNABLE ,如果不做中断标志判断,能否暂停或停止?

答案可以是能,也可以是不能。如果不介意 stop() 所带来的不安全问题,那么是可以停止(非暂停),调用后立刻抛出 ThreadDeath error 终止线程,但该方法存在风险,自行判断能否接受,关于 stop() 的风险,可以参考下面这篇文章 Java中的线程Thread方法之—stop() ,或查阅其他资料。除了这个方法,又不做中断判断,除了自行设置 中断/暂停标志 外,你的线程,嗯,对不起,当你 start() 后,它就不归你控制了。

3.线程的暂停操作

通过中断标志位判断,或者在中断异常中暂停线程,然后可以使用 Object.wait()等操作暂停,等待被唤起,或者保存此时线程内部对象状态,待需恢复时重新启动该线程。


线程终止、取消

1.怎么停止处于工作状态的线程,怎么取消一个未进入运行状态的线程?
  1. 使用中断方法 interrupt() 通过标志位或捕获异常块 return 出去。
  2. 取消一个未进入运行状态的线程,那么此时该线程处于 NEW 状态,或者 start() 后的可运行状态,使用中断后,在 run() 第一句判断是否处于中断中,若是,直接 return出线程。
  3. 线程启动后,它处于可运行状态,不能保证当前线程一定是处于非运行状态,所以可以使用 FutureFutureTaskcancel(boolean mayInterruptIfRunning) 来取消线程,通过传入参数控制是否中断线程(如果线程已经启动的话),如果线程未运行,则直接取消;如果已运行,则启动中断线程流程。

总结:

  • 当线程被启动,只有通过一些标志位的判断来中断运行过程,如果工作线程内部执行是一个顺序过程(A>B>C>D>E…)大量操作,且优先级一致,则会嵌套一堆判断,所以对于有些可能被取消,但线性执行的线程,我现在没有一个比较好的解决方案,如果有,以后再填坑。
  • 如果是线性执行,大量操作,但存在操作优先级的话,可以只判断优先级高的操作,能减轻代码量,但还是没什么用。
  • 如果可用循环执行,嵌套 for 的话,加个中断位判断;如果是有 sleep wait 等操作,加个异常捕获操作。对于这种理想型线程,自定义一个标志位,或者利用 Futurecancel(bool),轻松达到取消暂停线程的目的。

猜你喜欢

转载自blog.csdn.net/ganfanzhou/article/details/80558860