来源:木杉的博客 ,
imushan.com/2018/08/01/java/language/JDK源码阅读-InterruptibleChannel与可中断IO/
Java传统IO是不支持中断的,所以如果代码在read/write等操作阻塞的话,是无法被中断的。这就无法和Thead的interrupt模型配合使用了。JavaNIO众多的升级点中就包含了IO操作对中断的支持。InterruptiableChannel表示支持中断的Channel。我们常用的FileChannel,SocketChannel,DatagramChannel都实现了这个接口。
InterruptibleChannel接口
public interface InterruptibleChannel extends Channel{
/**
* 关闭当前Channel
*
* 任何当前阻塞在当前channel执行的IO操作上的线程,都会收到一个AsynchronousCloseException异常
*/
public void close() throws IOException;
}
InterruptibleChannel接口没有定义任何方法,其中的close方法是父接口就有的,这里只是添加了额外的注释。
AbstractInterruptibleChannel实现了InterruptibleChannel接口,并提供了实现可中断IO机制的重要的方法,比如begin(),end()。
在解读这些方法的代码前,先了解一下NIO中,支持中断的Channel代码是如何编写的。
第一个要求是要正确使用begin()和end()方法:
boolean completed = false;
try {
begin();
completed = ...; // 执行阻塞IO操作
return ...; // 返回结果
} finally {
end(completed);
}
NIO规定了,在阻塞IO的语句前后,需要调用begin()和end()方法,为了保证end()方法一定被调用,要求放在finally语句块中。
第二个要求是Channel需要实现java.nio.channels.spi.AbstractInterruptibleChannel#implCloseChannel这个方法。AbstractInterruptibleChannel在处理中断时,会调用这个方法,使用Channel的具体实现来关闭Channel。
接下来我们具体看一下begin()和end()方法是如何实现的。
begin方法
// 保存中断处理对象实例
private Interruptible interruptor;
// 保存被中断线程实例
private volatile Thread interrupted;
protected final void begin(){
// 初始化中断处理对象