Java中断及中断响应
跳到导航
跳到搜索
中断机制
Java的中断为协作机制,即 A 不能直接中断 B,而是调用 “B.interrupt()” 来申请中断 B (设置中断状态);然后由 B 通过 “interrupted()”(会重置中断状态)或 “isInterrupted()”(不会重置中断状态)读取中断状态,并决定如何响应。
中断相关源码
private volatile Interruptible blocker; //
private final Object blockerLock = new Object(); // 用于synchronized锁定,实现同步安全
/* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
*/
void blockedOn(Interruptible b) {
synchronized (blockerLock) {
blocker = b;
}
}
...
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); // 调用Interruptible对象b 的同步方法
return;
}
}
interrupt0();
}
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
public boolean isInterrupted() {
return isInterrupted(false);
}
private native boolean isInterrupted(boolean ClearInterrupted);
...
private native void interrupt0();
其中:
- “interrupt()” 方法只是调用了“blocker.interrupt()”和“interrupt0()”,并不对线程运行产生影响;
- “blocker”域用于 nio 的中断?【???待查证】
- “interrupt0()” 是一个 native方法,仅用于设置中断标识(其他的);
- “interrupted()”(静态方法)和“isInterrupted()”(实例方法)最终都是调用本地方法“isInterrupted”;
- “isInterrupted”是一个 native方法,用于判断中断标识,并根据参数决定是否重置中断状态;
- 中断标识的使用,都是在native方法中。
请求中断
Java的中断:
- 没有可以强制线程终止的方法。
- interrupt 方法用于请求终止线程。
中断响应
Java 中,使用“interrupt()”方法请求中断,并不会改变线程运行状态,只是改变了线程中断信号。
中断处理的两种方式:
- 对于不响应中断的方法,需要通过代码方法轮询中断状态,看看它是否被请求停止正在做的事情;
- “isInterrupted”:获取中断标识;
- “interrupted”获取并清楚中断标识;
- 响应中断的方法,会抛出InterruptedException异常(并重置中断标识),处理该异常即可;
响应中断的方法
- 可从源码注释中看出,方法是否响应中断;
/* * ... * * <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}. * * ... */
- 若方法使线程进入可取消的阻塞状态、等待或是超时等待的状态,则会响应中断;
- 如:“Object.wait”、“Thread.join”、“Thread.sleep”、“LockSupport.park”等方法。
- 对于不可取消的阻塞状态,(如:获取锁操作是不能被中断的,要一直阻塞等到到它获取到锁为止),则该方法不会响应中断;
- 如:“synchronized”的方法或是代码块,“ReentrantLock.lock”方法。
- 可以使用“ReentrantLock.lockInterruptibly”方法响应中断(ReentrantLock底层是使用LockSupport.park方法进行等待的);
- 也可以使用超时锁“Lock.tryLock(timeout,unit)”,在超时后会抛出异常;
InterruptedException 处理
如果抛出 InterruptedException 意味着一个方法是阻塞方法,那么调用一个阻塞方法则意味着您的方法也是一个阻塞方法,而且您应该有某种策略来处理 InterruptedException。
对于 InterruptedException:
- (最糟糕的方式是 “生吞(swallow)”:即,捕捉它,然后什么也不做)。
- 通常最容易的策略是直接抛出 InterruptedException(需要方法“throws InterruptedException”):
try { sleep(delay); } catch (InterruptedException e) { throw e; }
- 在catch子句中调用Thread.currentThread.interrupt()来重设中断状态位(因为抛出中断异常后,中断状态位会被清除,即false)
try { sleep(delay); } catch (InterruptedException e) { Thread.currentThread().isInterrupted(); }