• Thread.interrupt()方法理解


    原博客地址:
    多线程编程 实战篇 (四)

    不客气地说,至少有一半人认为,线程的”中断”就是让线程停止。
    如果你也这么认为,那你对多线程编程还没有入门。

    在java中,线程的中断(interrupt)只是改变了线程的中断状态,至于这个中断状态改变后带来的结果,那是无法确定的,有时它更是让停止中的线程继续执行的唯一手段。不但不是让线程停止运行,反而是继续执行线程的手段。

    对于执行一般逻辑的线程,如果调用它的interrupt()方法,那么对这个线程没有任何
    影响,比如线程a正在执行:
    while(条件) x ++;
    这样的语句,如果其它线程调用a.interrupt();那么并不会影响a对象上运行的线程,但中断标志会变为true。如果在其它线程里再次测试a的中断状态,则中断标志为true,但并不会停止这个线程的运行。

    在一个线程对象上调用interrupt()方法,真正有影响的是wait,join,sleep方法,当然这三个方法包括它们的重载方法。

    请注意:[上面这三个方法都会抛出InterruptedException],记住这句话,下面我会重复。一个线程在调用interrupt()后,自己不会抛出InterruptedException异常,所以你看到interrupt()并没有抛出这个异常,所以我上面说如果线程a正在执行while(条件) x ++;你调用a.interrupt()后线程会继续正常地执行下去.
    附:
    Thread.sleep()源码:

    public static native void sleep(long millis) throws InterruptedException;

    Object.wait()源码:

    public final native void wait(long timeout) throws InterruptedException;

    Thread.join()源码

    public final synchronized void join(long millis) throws InterruptedException {
        ...
    }

    但是,如果一个线程被调用了interrupt()后,它的状态是阻塞状态的。而且这个状态是由于正在执行wait,join,sleep的线程导致的,那么是会改变线程的运行结果.

    一. 对于wait中的等待notify、notifyAll换新的线程,其实这个线程已经“暂停”执行,因为它正在某一对象的休息室中,这时如果它的中断状态被改变,那么它就会抛出异常。这个InterruptedException异常不是线程抛出的,而是wait方法,也就是对象的wait方法内部会不断检查在此对象上休息的线程的状态,如果发现哪个线程的状态被置为已中断,则会抛出InterruptedException,意思就是这个线程不能再等待了,其意义就等同于唤醒它了,然后执行catch中的代码。

    这里唯一的区别是,被nortify/All唤醒的线程会继续执行wait下面的语句,而在wait
    中被中断的线程则将控制权交给了catch语句。一些正常的逻辑要被放到catch中来运行。但有时这是唯一手段,比如一个线程a在某一对象b的wait中等待唤醒,其它线程必须获取到对象b的监视锁才能调用b.notify()[All],否则你就无法唤醒线程a,但在任何线程中可以无条件地调用a.interrupt();唤醒后的逻辑你要放在catch中,当然同notify/All一样,继续执行a线程的条件还是要等拿到b对象的监视锁。

    二. 对于sleep中的线程,如果你调用了Thread.sleep(一年);现在你后悔了,想让它早
    些醒过来,调用interrupt()方法就是唯一手段,只有改变它的中断状态,让它从sleep中将控制权转到处理异常的catch语句中,然后再由catch中的处理转换到正常的逻辑。同样,对于join中的线程你也可以这样处理。

    对于一般介绍多线程模式的书上,他们会这样来介绍:当一个线程被中断后,在进入wait,sleep,join方法时会抛出异常。是的,这一点也没有错,但是这有什么意义呢?如果你知道那个线程的状态已经处于中断状态,为什么还要让它进入这三个方法呢?当然有时是必须这么做的,但大多数时候没有这么做的理由,所以我上面主要介绍了在已经调用这三个方法的线程上调用interrupt()方法让它从这几个方法的”暂停”状态中恢复过来。这个恢复过来就可以包含两个目的:
    一. [可以使线程继续执行],那就是在catch语句中执行醒来后的逻辑,或由catch语句
    转回正常的逻辑。总之它是从wait,sleep,join的暂停状态活过来了。
    二. [可以直接停止线程的运行],当然在catch中什么也不处理,或return,那么就完成了当前线程的使命,可以使在上面”暂停”的状态中立即真正的”停止”。

  • 相关阅读:
    优化SQL查询:如何写出高性能SQL语句
    提高SQL执行效率的16种方法
    Spring Ioc DI 原理
    java内存泄漏
    转:js闭包
    LeetCode Best Time to Buy and Sell Stock III
    LeetCode Best Time to Buy and Sell Stock with Cooldown
    LeetCode Length of Longest Fibonacci Subsequence
    LeetCode Divisor Game
    LeetCode Sum of Even Numbers After Queries
  • 原文地址:https://www.cnblogs.com/loren-Yang/p/7466123.html
Copyright © 2020-2023  润新知