【jvm】中断深入理解,线程池,AQS都在使用的利器

1 线程中断:

java中对于中断的大部分操作无外乎以下两点:

  • 设置或者清除中断标志位(对运行状态线程需要自检,堵塞状态会抛出异常)
  • 抛出InterruptedException

2 设置中断

直接看源码 :对上面的两个操作说的很清晰了

    /**
     * Interrupts this thread.
     *
     * <p> Unless the current thread is interrupting itself, which is
     * always permitted, the {@link #checkAccess() checkAccess} method
     * of this thread is invoked, which may cause a {@link
     * SecurityException} to be thrown.
     *
     * // 抛异常 前置条件,线程处于堵塞状态,中断信号用完即消失,不会保存
     * <p> If this thread is blocked in an invocation of the {@link
     * Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link
     * Object#wait(long, int) wait(long, int)} methods of the {@link Object}
     * class, or of the {@link #join()}, {@link #join(long)}, {@link
     * #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)},
     * methods of this class, then its interrupt status will be cleared and it
     * will receive an {@link InterruptedException}.
     *
     * <p> If this thread is blocked in an I/O operation upon an {@link
     * java.nio.channels.InterruptibleChannel InterruptibleChannel}
     * then the channel will be closed, the thread's interrupt
     * status will be set, and the thread will receive a {@link
     * java.nio.channels.ClosedByInterruptException}.
     *
     * <p> If this thread is blocked in a {@link java.nio.channels.Selector}
     * then the thread's interrupt status will be set and it will return
     * immediately from the selection operation, possibly with a non-zero
     * value, just as if the selector's {@link
     * java.nio.channels.Selector#wakeup wakeup} method were invoked.
     * // 无前置条件,只是设置了中断状态字段,线程需要自检使用。入过设置中断后,再进入堵塞,OS不会发送中断信号
     * <p> If none of the previous conditions hold then this thread's interrupt
     * status will be set. </p>
     *
     * <p> Interrupting a thread that is not alive need not have any effect.
     *
     * @throws  SecurityException
     *          if the current thread cannot modify this thread
     *
     * @revised 6.0
     * @spec JSR-51
     */
    public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }

3 自检

isInterrupted() 和 interrupted() 方法只涉及到中断状态的查询,最多是多加一步重置中断状态,并不牵涉到InterruptedException。
interrupted()是我们清除中断的唯一方法 

看源码:

  /**
     * Tests whether the current thread has been interrupted.  The
     * <i>interrupted status</i> of the thread is cleared by this method.  In
     * other words, if this method were to be called twice in succession, the
     * second call would return false (unless the current thread were
     * interrupted again, after the first call had cleared its interrupted
     * status and before the second call had examined it).
     *
     * <p>A thread interruption ignored because a thread was not alive
     * at the time of the interrupt will be reflected by this method
     * returning false.
     *
     * @return  <code>true</code> if the current thread has been interrupted;
     *          <code>false</code> otherwise.
     * @see #isInterrupted()
     * @revised 6.0
     */
    public static boolean interrupted() {
        return currentThread().isInterrupted(true);  // true clean signal(cleared its interrupted)
    }

 /**
     * Tests whether this thread has been interrupted.  The <i>interrupted
     * status</i> of the thread is unaffected by this method.
     *
     * <p>A thread interruption ignored because a thread was not alive
     * at the time of the interrupt will be reflected by this method
     * returning false.
     *
     * @return  <code>true</code> if this thread has been interrupted;
     *          <code>false</code> otherwise.
     * @see     #interrupted()
     * @revised 6.0
     */
    public boolean isInterrupted() {
        return isInterrupted(false);
    }

    /**
     * Tests if some Thread has been interrupted.  The interrupted state
     * is reset or not based on the value of ClearInterrupted that is
     * passed.
     */
    private native boolean isInterrupted(boolean ClearInterrupted); //底层ClearInterrupted控制清除与否

4 使用举例

   我们可以使用Thread#interrupt中断一个线程,被中断的线程所受的影响为以下两种之一:

  •     若被中断前,该线程处于非阻塞状态,那么该线程的中断状态被设为true, 除此之外,不会发生任何事。
  •     若被中断前,该线程处于阻塞状态(调用了wait,sleep,join等方法,那么该线程将会立即从阻塞状态中退出,并抛出一个InterruptedException异常,同时,该线程的中断状态被设为false(操作系统默认操作), 除此之外,不会发生任何事。
 public static void main(String[] args) throws InterruptedException {

        Thread thread = new Thread(()-> {
            try {
                Thread.sleep(7000);
                System.out.println("我醒了 被中断过 = " + Thread.interrupted());

                System.out.println(Thread.activeCount());

            } catch (InterruptedException e) {
                System.out.println(e);
                e.printStackTrace();
                System.out.println("我被中断醒了  = " + Thread.interrupted());

            }
        });
        thread.setDaemon(false);
        thread.start();
        // 需要结合blockerLock使用
        thread.interrupt();// 开始之后设置中断

        System.in.read();
}

// 输出
我被中断醒了  = false

响应中断的方式举例

  • public final native void wait(long timeout) throws InterruptedException;// Obejct class 搭配Synchronized同步器使用,通过异常方式通知
    java.util.concurrent.locks.LockSupport#park(java.lang.Object)  // 会导致LockSupport.park 立即返回,同时Thread的中断信号被设置   
    

 

5 小结

  1. 中断异常一般是线程被中断后,在一些block类型的方法(如wait,sleep,join)中抛出。有些像gc的安全域,安全点。(可以先设置中断标志,然后进入sleep也会立即抛出异常)
  2. 当一个线程因为调用wait,sleep,join方法而进入阻塞状态后,若在这时中断这个线程,则这些方法将会抛出InterruptedException异常,我们可以利用这个异常,使线程跳出阻塞状态,从而终止线程。
  3. 中断一个处于运行状态的线程只会将该线程的中断标志位设为true, 而并不会抛出InterruptedException异常,为了能在运行过程中感知到线程已经被中断了,我们只能通过不断地检查中断标志位来实现:
  4. 中断一个线程,只是传递了请求中断的消息,并不会直接阻止一个线程的运行。


 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页