最近两天看nio的时候发现一个问题,
Selector的创建
通过调用Selector.open()方法创建一个Selector,如下:
Selector selector = Selector.open();
向Selector注册通道
为了将Channel和Selector配合使用,必须将channel注册到selector上。通过SelectableChannel.register()方法来实现,如下:
channel.configureBlocking(false);
SelectionKey key = channel.register(selector,Selectionkey.OP_READ);
与Selector一起使用时,Channel必须处于非阻塞模式下。这意味着不能将FileChannel与Selector一起使用,因为FileChannel不能切换到非阻塞模式。而套接字通道都可以。
以上从Java NIO系列教程(六) Selector看到的内容
上面有一句话 FileChannel不能切换到非阻塞模式 我翻了好几个博客,发现大家都是将这句话写下了,没解释原因。我就自己记录一下原因
首先先 FileChannel 的部分源码
public abstract class FileChannel
extends AbstractInterruptibleChannel
implements SeekableByteChannel, GatheringByteChannel, ScatteringByteChannel
{
/**
* Initializes a new instance of this class.
*/
protected FileChannel() { }
........
}
FileChannel继承自AbstractInterruptibleChannel
还有以一个抽象类继承了AbstractInterruptibleChannel,这个类是 SelectableChannel
代码如下
public abstract class SelectableChannel
extends AbstractInterruptibleChannel
implements Channel
{
/**
* Initializes a new instance of this class.
*/
protected SelectableChannel() { }
......
/**
* Adjusts this channel's blocking mode.
*
* <p> If this channel is registered with one or more selectors then an
* attempt to place it into blocking mode will cause an {@link
* IllegalBlockingModeException} to be thrown.
*
* <p> This method may be invoked at any time. The new blocking mode will
* only affect I/O operations that are initiated after this method returns.
* For some implementations this may require blocking until all pending I/O
* operations are complete.
*
* <p> If this method is invoked while another invocation of this method or
* of the {@link #register(Selector, int) register} method is in progress
* then it will first block until the other operation is complete. </p>
*
* @param block If <tt>true</tt> then this channel will be placed in
* blocking mode; if <tt>false</tt> then it will be placed
* non-blocking mode
*
* @return This selectable channel
*
* @throws ClosedChannelException
* If this channel is closed
*
* @throws IllegalBlockingModeException
* If <tt>block</tt> is <tt>true</tt> and this channel is
* registered with one or more selectors
*
* @throws IOException
* If an I/O error occurs
*/
public abstract SelectableChannel configureBlocking(boolean block)
throws IOException;
......
}
在SelectableChannel中有configureBlocking方法,
AbstractInterruptibleChannel中没有此方法,FileChannel类中也没有此方法。
所以从源码的角度分析FileChannel不能切换到非阻塞模式,这就是原因。
欢迎大家加群:835870546
大家可以一起交流学习!