java线程暂停和恢复 线程暂停和恢复( 二 )


3. suspend()、resume()、stop()suspend()、resume()、stop()这三个方法,分别对应着,线程暂停、线程恢复、线程停止 。观察Java源码,都被标识为@Deprecated,不建议使用了 。
首先我们看suspend()、resume(),它们必须成对出现,且有先后顺序 。那么为什么会被废弃呢?
因为线程调用suspend程序暂停后,不会释放任何资源,包括锁,且一直处于睡眠状态,容易引发死锁 。而resume因为要和suspend成对出现,所以也没有存在的必要 。
那么stop方法为什么不建议使用呢?我们先看源码:
@Deprecatedpublic final void stop() {SecurityManager security = System.getSecurityManager();if (security != null) {checkAccess();if (this != Thread.currentThread()) {security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);}}// A zero status value corresponds to "NEW", it can't change to// not-NEW because we hold the lock.if (threadStatus != 0) {resume(); // Wake up thread if it was suspended; no-op otherwise}// The VM can handle all thread statesstop0(new ThreadDeath());}最终通过调用stop0(new ThreadDeath())函数,stop0是Native函数,参数是ThreadDeath,ThreadDeath是一个异常对象,该对象从Native层抛到了Java层 。线程运行中遇到异常,会导致线程停止,不过不会引起程序退出 。
线程是因为异常而停止的,锁会释放,但是不会释放其他的资源,比如打开的socket连接或者IO,多不会关闭,引发内存泄漏 。
很多时候为了保证数据安全,线程中会编写同步代码,如果当线程正在执行同步代码时,此时调用stop,引起抛出异常,导致线程持有的锁会全部释放,此时就不能确保数据的安全性,出现无法预期的错乱数据,还有可能导致存在需要被释放的资源得不到释放,引发内存泄露 。所以用stop停止线程是不推荐的 。
4.优雅的终止线程关闭线程,肯定等到线程释放掉资源,以免造成内存泄漏,所以不建议使用stop方法 。那么应该怎么关闭线程呢?答案是两阶段终止模式 。
两阶段终止模式,顾名思义,分两个阶段 。第一个阶段,向线程发送终止指令,记住这里只是设置一个终止标识位 。第二阶段,线程响应指令,然后终止 。这里就用到了,Thread.interrupt()方法来设置终止标识位 。我们先看一张图如下:
想终止线程,也就是线程是终止状态,如上图所示,线程只能是RUNNABLE状态才可以到终止状态 。所以线程目前状态可以能是RUNNABLE状态,或者是休眠状态 。当线程是休眠状态,当我们设置中断标识位时,线程立马会抛出InterruptedException,并且JVM会清除中断标识位,所以在捕获InterruptedException异常后,需要重新设置中断标识位 。如下代码:
public class StopThread {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {System.out.println("worker-Thread start ...");while(!Thread.currentThread().isInterrupted()) {System.out.println("worker-Thread working ...");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();Thread.currentThread().interrupt();}}System.out.println("worker-Thread done ...");}, "worker-Thread");t.start();Thread.sleep(10000);t.interrupt();}}线程t每次执行while内代码,休眠1000ms,然后继续执行,主线程在休眠10000ms后,线程t设置中断标识位,此时,如果线程t还在sleep中,则抛出InterruptedException异常,JVM清除中断标识位,重新设置中断标识位后,下次执行while代码,条件不符合,线程执行完毕 。这样,就完成了两阶段模式 。
总结:

  1. 线程启动使用start方法,而线程run方法,不会启动一个线程 。
  2. Thread.interrupt(),设置中断标识位,具体是否结束线程,线程自己控制 。


    以上关于本文的内容,仅作参考!温馨提示:如遇健康、疾病相关的问题,请您及时就医或请专业人士给予相关指导!

    「四川龙网」www.sichuanlong.com小编还为您精选了以下内容,希望对您有所帮助: