目录
方法isRegistered,keyFor,2个register
方法configureBlocking,isBlocking,blockingLock
简介
package java.nio.channels;
import java.io.IOException;
import java.nio.channels.spi.AbstractInterruptibleChannel;
import java.nio.channels.spi.SelectorProvider;
/**
* 一种可以通过选择器多路复用的信道。
*
* <p> 为了与选择器一起使用,必须首先通过register(Selector,int,Object)方法注册此类的实例。
* 此方法返回一个新的SelectionKey对象,该对象表示通道在选择器中的注册。
*
* <p> 一旦使用选择器注册,通道将保持注册状态,直到取消注册。
* 这包括释放选择器分配给通道的所有资源。
*
* <p> 不能直接注销通道;
* 相反,必须取消代表其注册的键。
* 取消键请求在选择器的下一个选择操作期间取消注册通道。
* 可以通过调用键的cancel方法显式取消键。
* 当通道关闭时,通道的所有键都会被隐式取消,
* 无论是通过调用它的close方法还是通过中断在通道上I/O操作中阻塞的线程。
*
* <p> 如果选择器本身关闭,则信道将被注销,代表其注册的密钥将失效,不再延迟。
*
* <p> 一个频道最多可以用任何特定选择器注册一次。
*
* <p> 通道是否注册到一个或多个选择器可以通过调用isRegistered方法来确定。
*
* <p> 多个并发线程可以安全地使用可选通道。 </p>
*
*
* <a name="bm"></a>
* <h2>阻塞方式</h2>
*
* 可选择的信道处于阻塞模式或非阻塞模式。
* 在阻塞模式下,通道上调用的每个I/O操作都将阻塞,直到完成。
* 在非阻塞模式下,I/O操作永远不会阻塞,传输的字节数可能少于请求的字节数,或者根本就没有字节数。
* 可选择通道的阻塞模式可以通过调用其isBlocking方法来确定。
*
* <p> 新创建的可选频道始终处于阻塞状态模式。
* 非阻塞模式与基于选择器的多路复用一起使用最为有用。
* 在向选择器注册之前,必须将通道置于非阻塞模式,并且在取消注册之前不能返回到阻塞模式。
*
*
* @author Mark Reinhold
* @author JSR-51 Expert Group
* @since 1.4
*
* @see SelectionKey
* @see Selector
*/
public abstract class SelectableChannel
extends AbstractInterruptibleChannel
implements Channel
构造函数,方法provider,validOps
/**
* 初始化一个新的实例
*/
protected SelectableChannel() { }
/**
* 返回创建此频道的提供程序。
*
* @return The provider that created this channel
*/
public abstract SelectorProvider provider();
/**
* 返回标识此通道支持的操作的操作集。
* 在这个整数值中设置的位正好表示对这个通道有效的操作。
* 对于给定的具体的通道类,此方法始终返回相同的值。
*
* @return The valid-operation set
*/
public abstract int validOps();
方法isRegistered,keyFor,2个register
// 内部状态
// keySet, 可以是空的,但不会为null,通常是一个小数组
// boolean isRegistered, 由keyset保护
// regLock, 防止重复注册的锁对象
// boolean isBlocking, 由regLock保护
/**
* 指示此频道当前是否已注册到任何选择器。新创建的频道未注册。
*
* <p> 在取消注册的通道中,由于密钥在取消注册后的某个时间内被取消,因此可能会保留密钥。
* 通道也可以在关闭后的一段时间内保持注册状态。</p>
*
* @return <tt>true</tt> if, and only if, this channel is registered
*/
public abstract boolean isRegistered();
//
// sync(keySet) { return isRegistered; }
/**
* 检索表示频道注册到给定的选择器的密钥。
*
* @param sel
* The selector
*
* @return The key returned when this channel was last registered with the
* given selector, or <tt>null</tt> if this channel is not
* currently registered with that selector
*/
public abstract SelectionKey keyFor(Selector sel);
//
// sync(keySet) { return findKey(sel); }
/**
* 用给定的选择器注册此通道,返回selectionkey。
*
* <p> 如果此频道已经使用给定的选择器注册,则返回表示该注册的选择键。
* 键的interest set将被更改为ops,就像调用SelectionKey.interestOps(int)方法一样。
* 如果att参数不为null,则键的attachments将被设置为该值。
* 如果密钥已被取消,则将引发CancelledKeyException。
*
* <p> 否则,此频道尚未向给定的选择器注册,因此它被注册,生成的新密钥被返回。
* key的初始interest set是ops,它的attachment是att。
*
* <p> 可以随时调用此方法。
* 如果在对另一个该方法或configureBlocking方法的调用时调用此方法,则它将首先阻塞,直到另一个操作完成。
* 然后,此方法将在选择器的密钥集上同步,因此,
* 如果与涉及同一选择器的另一个注册或选择操作同时调用,则可能会阻塞。</p>
*
* <p>如果此通道在操作过程中关闭,则此方法返回的密钥将被取消,因此将无效。</p>
*
* @param sel
* The selector with which this channel is to be registered
*
* @param ops
* The interest set for the resulting key
*
* @param att
* The attachment for the resulting key; may be <tt>null</tt>
*
* @throws ClosedChannelException
* If this channel is closed
*
* @throws ClosedSelectorException
* If the selector is closed
*
* @throws IllegalBlockingModeException
* If this channel is in blocking mode
*
* @throws IllegalSelectorException
* If this channel was not created by the same provider
* as the given selector
*
* @throws CancelledKeyException
* If this channel is currently registered with the given selector
* but the corresponding key has already been cancelled
*
* @throws IllegalArgumentException
* If a bit in the <tt>ops</tt> set does not correspond to an
* operation that is supported by this channel, that is, if
* {@code set & ~validOps() != 0}
*
* @return A key representing the registration of this channel with
* the given selector
*/
public abstract SelectionKey register(Selector sel, int ops, Object att)
throws ClosedChannelException;
//
// sync(regLock) {
// sync(keySet) { look for selector }
// if (channel found) { set interest ops -- may block in selector;
// return key; }
// create new key -- may block somewhere in selector;
// sync(keySet) { add key; }
// attach(attachment);
// return key;
// }
/**
* 用给定的选择器注册此通道,返回selectionkey。
*
* <p> 这种调用的形式
*
* <blockquote><tt>sc.register(sel, ops)</tt></blockquote>
*
* 与下面的调用相同
*
* <blockquote><tt>sc.{@link
* #register(java.nio.channels.Selector,int,java.lang.Object)
* register}(sel, ops, null)</tt></blockquote>
*
* @param sel
* The selector with which this channel is to be registered
*
* @param ops
* The interest set for the resulting key
*
* @throws ClosedChannelException
* If this channel is closed
*
* @throws ClosedSelectorException
* If the selector is closed
*
* @throws IllegalBlockingModeException
* If this channel is in blocking mode
*
* @throws IllegalSelectorException
* If this channel was not created by the same provider
* as the given selector
*
* @throws CancelledKeyException
* If this channel is currently registered with the given selector
* but the corresponding key has already been cancelled
*
* @throws IllegalArgumentException
* If a bit in <tt>ops</tt> does not correspond to an operation
* that is supported by this channel, that is, if {@code set &
* ~validOps() != 0}
*
* @return A key representing the registration of this channel with
* the given selector
*/
public final SelectionKey register(Selector sel, int ops)
throws ClosedChannelException
{
return register(sel, ops, null);
}
方法configureBlocking,isBlocking,blockingLock
/**
* 通道阻塞模式调整。
*
* <p> 如果这个通道是用一个或多个选择器注册的,
* 那么试图将它置于阻塞模式将导致抛出一个IllegalBlockingModeException。
*
* <p> 可以随时调用此方法。
* 新的阻塞模式只会影响在此方法之后启动的I/O操作返回。
* 为有些实现可能需要阻塞,直到所有挂起的I/O操作完成。
*
* <p> 如果在对该方法或register(Selector, int)方法的另一次调用正在进行时调用此方法,
* 则它将首先阻塞,直到另一个操作完成。</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;
//
// sync(regLock) {
// sync(keySet) { throw IBME if block && isRegistered; }
// change mode;
// }
/**
* 告诉此通道上的每个I/O操作在完成之前是否都会阻塞。
* 新创建的通道始终处于阻塞模式。
*
* <p> 如果关闭此通道,则不指定此方法返回的值。 </p>
*
* @return <tt>true</tt> if, and only if, this channel is in blocking mode
*/
public abstract boolean isBlocking();
/**
* 检索configureBlocking和register方法所基于的对象同步。
* 这个在需要短期维护特定块模式的适配器的实现中通常很有用。
*
* @return The blocking-mode lock object
*/
public abstract Object blockingLock();