谈谈我所了解的中断吧计算机世界所说的中断为什么需要中断机

计算机世界所说的中断

谈到中断,我们总是习惯性的想到中断就是将正在进行这件事打断。但是,在计算机世界,中断可能不是这么简单。从计算机设计的角度考虑,如果中断就是强行打断某些正在进行中的线程的话,这很可能造成不可挽回的后果。

所以,计算机对于打断的设计得更圆滑一点,当我们需要进行打断操作的时候,计算机仅仅是做一个打断的通知,具体什么时候打断,由收到打断信号的线程自己做决定。

为什么需要中断机制

在日常开发中,我们不能保证每一个线程都会按照我们预期的方向执行下去,总会由于一些问题导致线程处于自旋浪费资源的状态。
关于自旋的概念可以参考这篇文章
# 互斥锁与自旋锁

java中的中断方法

interrupt

从源码中不难看出,这个是线程类唯一一个可以设置中断状态的方法,其实现原理也很简单,直接调用native方法interrupt0完成设置中断( 简单地讲,一个Native Method就是一个java调用非java代码的接口。一个Native Method是这样一个java的方法:该方法的实现由非java语言实现,比如C。这个特征并非java所特有,很多其它的编程语言都有这一机制,比如在C++中,你可以用extern “C”告知C++编译器去调用一个C的函数。)。

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();
}
复制代码

interrupted

这个函数通过源码我们不难看出,他会判断当前线程的中断状态,若被中断则返回true,且会将中断状态的标记设置为false。

public static boolean interrupted() {
    return currentThread().isInterrupted(true);
}
复制代码
/**
 * 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);
复制代码

可能有些读者读到这里会有点不明白这个方法的含义,我们就以一段代码对这个方法进行解释

Thread.currentThread().isInterrupted(); // true 当前线程已被中断
Thread.interrupted() // true,表示当前线程已被中断,然后将中断标记设置为false
Thread.currentThread().isInterrupted(); // false
Thread.interrupted() // false
复制代码

isInterrupted

这个函数不必多说,当线程被中断则返回true,若被清除中断状态(即被上述的interrupted清除了true的状态标记)或者还未中断则返回false。

public boolean isInterrupted() {
    return isInterrupted(false);
}
复制代码

使用中断的注意事项

原则1

如果调用可被中断的方法,那么他的方法签名上必然会有throw InterruptedException,当你在调用过程中抛出InterruptedException时,你可以不断将其向上抛出,是当前方法成为一个可被中断的方法。确保这个方法遇到故障时也能被成功检测并中断。

原则2

当然,你可能会在日常开发中无法做到总是抛出InterruptedException,所以为了保证故障的线程能被成功中断,对于没有加上throw InterruptedException的方法,必须捕获这个异常,并手动将其中断,如下所示:

 Thread th = Thread.currentThread();
        while (true) {
            if (th.isInterrupted()) {
                break;
            }
            // todo something
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
                //在catch时将其打断,否则就会无线循环,线程永不停止
                th.interrupt();
            }
        }
复制代码
* @throws  InterruptedException
 *          if any thread has interrupted the current thread. The
 *          <i>interrupted status</i> of the current thread is
 *          cleared when this exception is thrown.
 */
public static native void sleep(long millis) throws InterruptedException;
复制代码

可以看出这段代码中线程调用了sleep,但是翻看sleep代码注释我们发现,当休眠发生异常时会抛出InterruptedException当前线程的中断状态会被重置。所以为了保证线程能够跳出while,我们必须在catch块中将其手动设置中断标记以确保出错时,这个野线程能够被及时中断而避免资源浪费。

从源码中查看中断

ThreadPoolExecutor shutdownNow

我们自顶向下可以看出,shutdownNow底层就是通过interrupt来中断所有的工作线程。

public List<Runnable> shutdownNow() {
    List<Runnable> tasks;
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        checkShutdownAccess();
        advanceRunState(STOP);
        interruptWorkers();
        tasks = drainQueue();
    } finally {
        mainLock.unlock();
    }
    tryTerminate();
    return tasks;
}
复制代码
private void interruptWorkers() {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        for (Worker w : workers)
            w.interruptIfStarted();
    } finally {
        mainLock.unlock();
    }
}
复制代码
void interruptIfStarted() {
    Thread t;
    if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
        try {
            t.interrupt();
        } catch (SecurityException ignore) {
        }
    }
}
复制代码

FutureTask cancel

public boolean cancel(boolean mayInterruptIfRunning) {
    if (!(state == NEW &&
          UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
              mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
        return false;
    try {    // in case call to interrupt throws exception
        if (mayInterruptIfRunning) {
            try {
                Thread t = runner;
                if (t != null)
                    t.interrupt();
            } finally { // final state
                UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
            }
        }
    } finally {
        finishCompletion();
    }
    return true;
}
复制代码