notify keyword 就是 word try catch 逻辑 n) 这也 bsp
今天我们聊聊 Java 线程的中断机制。
线程中断机制提供了一种方法,用于将线程从阻塞等待中唤醒,并作出相应的“受控中断”处理。
- synchronized(lock) {
- try {
- while (!check()) {
- lock.wait(1000);
- }
- } catch(InterruptedException e) {
- e.printStackTrace();
- }
- }
这段代码使用了 Java 提供的
机制,线程执行
- wait/notify
会阻塞,有三种情况使线程恢复运行。
- lock.wait()
这也会正常执行下一句代码。
- synchronized(lock) {
- lock.notifyAll(); // or lock.notify();
- }
被“中断”的线程 a,会在
- // 拿到等待中的线程的引用
- Thread a;
- a.interrupt();
处抛出
- lock.wait()
异常。
- InterruptedException
综上所述,你可以认为
内部在做这些事:
- object.wait()
- boolean checkTimeout = timeout > 0;
- Thread current = Thread.currentThread();
- lock.addWaiter(current);
- while (!current.isNotified()) {
- if (current.isInterrupted()) {
- current.clearInterrupted();
- throw new InterruptedException();
- }
- if (checkTimeout) {
- if (timeout == 0) break;
- timeout--;
- }
- }
这不完全准确,因为 wait 不使用这种“忙轮询”的方式做检查,但关于标志位的判断逻辑是正确的。
让我们从手动中断开始探究,
- // sun.nio.ch.Interruptible
- public interface Interruptible {
- void interrupt(Thread var1);
- }
- // java.lang.Thread
- private volatile Interruptible blocker;
- private final Object blockerLock = new Object();
- public void interrupt() {
- if (this != Thread.currentThread())
- checkAccess();
- synchronized (blockerLock) {
- Interruptible b = blocker;
- if (b != null) {
- interrupt0();
- b.interrupt(this);
- return;
- }
- }
- interrupt0();
- }
- // Just to set the interrupt flag
- private native void interrupt0();
能够看出,
先判断权限,然后实际调用
- thread.interrupt()
设置线程的中断标志,如果当前线程有 nio 的
- interrupt0()
那么还会回调它。
- Interruptible
一个线程怎么知道自己被打断了?
- // java.lang.Thread
- public static boolean interrupted() {
- return currentThread().isInterrupted(true);
- }
- public boolean isInterrupted() {
- return isInterrupted(false);
- }
- private native boolean isInterrupted(boolean clearInterrupted);
也就是说,
会返回线程是否被打断,并根据需要清空中断标志。
- isInterrupted(boolean)
我们发现,当一个线程并不阻塞,没有在
,
- object.wait()
,
- thread.join()
等不受 Java 程序逻辑控制的区域时,那么线程是否被打断只能通过检查中断标志得知。
- Thread.sleep()
当一个函数调用可能阻塞,Java 会在阻塞的源头签名里标记
,并要求编写
- throws InterruptedException
处理中断。
- try catch
当线程阻塞,就像上文所述,Java 检查到中断标志,先将其清除,然后抛出
。
- InterruptedException
- // java.lang.Object
- public final void wait() throws InterruptedException {
- wait(0);
- }
- public final native void wait(long timeout) throws InterruptedException;
如果一个线程收到
,之后仍然执行了会引发阻塞的代码,它将像“没事人”一样继续阻塞住。因为 Java 在内部将中断标志清除了!
- InterruptedException
我们常见地编写以下三类处理
的代码:
- InterruptedException
将
交由上层处理。
- InterruptedException
- public void foo() throws InterruptedException {
- synchronized(lock) {
- lock.wait();
- }
- }
遇到
重设中断标志位。
- InterruptedException
- try {
- synchronized(lock) {
- lock.wait();
- }
- } catch(InterruptedException e) {
- Thread.currentThread().interrupt();
- //break;
- }
先忙完,再重新抛出
。
- InterruptedException
- public void bar() throws InterruptedException {
- InterruptedException ie = null;
- boolean done = false;
- while (!done) {
- synchronized(lock) {
- try {
- lock.wait();
- } catch(InterruptedException e) {
- ie = e;
- continue;
- }
- }
- done = true;
- }
- if (ie != null) {
- throw ie;
- }
- }
如果一个线程无视中断标志和
,它仍然能够跑的很好。但 这与我们设计多线程的初衷是违背的 ,我们希望线程之间是和谐的有序协作以实现特定功能,因此 受控线程应当对中断作出响应 。而 Java 留给开发者这一自由,我们应当予以善用。如果你想学习java可以加我的学习群669823128
- InterruptedException
Java 线程的中断机制
来源: http://www.bubuko.com/infodetail-2423025.html