NIO SelectionKey

SelectionKey源码:

public abstract class SelectionKey {
	//以下四个常量是定义的通道的四种操作
	public static final int OP_READ = 1;
	public static final int OP_WRITE = 4;
	public static final int OP_CONNECT = 8;
	public static final int OP_ACCEPT = 16;
	//可以针对指定的通道附加一个对象 
	private volatile Object attachment = null;
	// 获得通道对象
	public abstract SelectableChannel channel();
	// 获得通道所注册的选择器
	public abstract Selector selector();
	// 验证通道和选择器之间的注册关系是否还生效
	public abstract boolean isValid();
	//将通道放入选择器的已注销集合中
	public abstract void cancel();
	//获得该通道所感兴趣的操作
	public abstract int interestOps();
	//设置通道感兴趣的操作
	public abstract SelectionKey interestOps(int paramInt);
	//获得通道已准备好的操作
	public abstract int readyOps();
	public final boolean isReadable() {
		return ((readyOps() & 0x1) != 0);
	}
	public final boolean isWritable() {
		return ((readyOps() & 0x4) != 0);
	}
	public final boolean isConnectable() {
		return ((readyOps() & 0x8) != 0);
	}
	public final boolean isAcceptable() {
		return ((readyOps() & 0x10) != 0);
	}
	public final Object attach(Object paramObject) {
		Object localObject = this.attachment;
		this.attachment = paramObject;
		return localObject;
	}
	public final Object attachment() {
		return this.attachment;
	}
}

SelectionKey(选择键对象)提供了下面方法

方法介绍
channel()获取关联的通道(SelectableChannel)
selector()获取关联的选择器(Selector)
isValid()验证维护选择器与通道关系的SelectionKey是否有效
cancel()取消键,调用一个已取消的键的方法将抛出CancelledKeyException
interestOps()获取这个key的兴趣(可选择操作)集合
interestOps(int ops)设置这个key的兴趣
readyOps()返回这个key准备好的操作集合(兴趣集合)
isReadable()检查选择键的兴趣是否为可读,实际上是通道的兴趣,选择键维护通道与选择器关系
isWritable()检查选择键的兴趣是否为可写
isConnectable()检查选择键的兴趣是否为连接
isAcceptable()检查选择键的兴趣是否为接受
attach(Object ob)设置一个Object数据到此key上
attachment()获取设置的Object数据

一个SelectionKey选择键对象包含两个以整数形式进行编码的比特掩码:

  • 一个用于指示那些通道/选择器组合体所关心的操作(instrest集合),
public abstract int interestOps();
  •  另一个表示通道准备好要执行的操作(ready集合)。可以通过调用键对象的interestOps( )方法来获取,这个interset集合永远不会被选择器改变,但可以通过调用选择键interestOps(int value )方法并传入一个新的比特掩码参数来改变它。
public abstract int readyOps();

     ready集合是interest集合的子集,可以通过调用键的readyOps( )方法来获取相关的通道的已经就绪的操作并且表示了interest集合中从上次调用select( )以来已经就绪的那些操作。

当我们调用选择器的select()方法时,会影响上述三种键的集合,调用之后会发生如下过程:

(1):已取消的键的集合将会被检查。如果它是非空的,每个已取消的键的集合中的键将从另外两个集合中移除,并且相关的通道将被注销。这个步骤结束后,已取消的键的集合将是空的。

(2):已注册的键的集合中的键的interest集合将被检查。在这个步骤中的检查执行过后,对interest集合的改动不会影响剩余的检查过程。一旦就绪条件被定下来,底层操作系统将会进行查询,以确定每个通道所关心的操作的真实就绪状态。依赖于特定的select( )方法调用,如果没有通道已经准备好,线程可能会在这时阻塞,通常会有一个超时值。直到系统调用完成为止,这个过程可能会使得调用线程睡眠一段时间,然后当前每个通道的就绪状态将确定下来。对于那些还没准备好的通道将不会执行任何的操作。对于那些操作系统指示至少已经准备好interest集合中的一种操作的通道,将执行以下两种操作中的一种:

   a.如果通道的键还没有处于已选择的键的集合中,那么键的ready集合将被清空,然后表示操作系统发现的当前通道已经准备好的操作的比特掩码将被设置。
   b.否则,也就是键在已选择的键的集合中。键的ready集合将被表示操作系统发现的当前已经准备好的操作的比特掩码更新。所有之前的已经不再是就绪状态的操作不会被清除。事实上,所有的比特位都不会被清理。由操作系统决定的ready集合是与之前的ready集合按位分离的,一旦键被放置于选择器的已选择的键的集合中,它的ready集合将是累积的。比特位只会被设置,不会被清理。

(3):步骤2可能会花费很长时间,特别是所激发的线程处于休眠状态时。与该选择器相关的键可能会同时被取消。当步骤2结束时,步骤1将重新执行,以完成任意一个在选择进行的过程中,键已经被取消的通道的注销。

select操作返回的值是ready集合在步骤2中被修改的键的数量,而不是已选择的键的集合中的通道的总数。返回值不是已准备好的通道的总数,而是从上一个select()调用之后进入就绪状态的通道的数量。之前的调用中就绪的,并且在本次调用中仍然就绪的通道不会被计入,而那些在前一次调用中已经就绪但已经不再处于就绪状态的通道也不会被计入。这些通道可能仍然在已选择的键的集合中,但不会被计入返回值中。返回值可能是0。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值