java selector 源码_Java NIO核心组件-Selector和Channel

昨天我们介绍了一下SelectorProvider和IO multiplexing.特别是IO multiplexing中的epoll系统调用,是Linux版本的Java的NIO的核心实现.

那今天我们就来介绍一下, Java NIO中的核心组件, Selector和Channel.这两个组件,对于熟悉Java OIO,而不熟悉Java NIO的朋友来说,理解其作用是极其不易的.

前提条件

在阅读这篇文章之前,如果各位不熟悉甚至没有听说过IO multiplexing中的epoll,请务必花时间去了解一下.了解了它们之后,就很容易理解Java NIO的实现了.

这里我们讲解的是Linux版本且内核版本大于2.6的Java NIO的实现,对于其他的系统或者内核版本较低的Java NIO,其具体实现是不一样的.

举例来说, Linux 内核版本大于等于2.6的Java NIO是采用epoll来实现的.而Linux内核版本小于2.6的Java NIO,则是采用poll来实现的.

Selector和Channel

Selector和Channel的关系,如下图所示:

a4d35d218235

各位如果了解过epoll的话,应该知道epoll_create操作会创建一个需要被监听的file descriptor.然后,epoll_ctl操作会为告诉内核,需要监听一个file descripitor的什么事件.最后,使用epoll_wait来告诉内核开始监听.

这里我们就可以把Selector比作epoll中的内核.把Channel比作epoll_create操作创建的file descriptor.这样就很容易理解了吧.

因为Java NIO实际上是给我们对IO multiplexing进行了封装,隐藏了其底层的实现.所以我们完全可以这样来理解.

贴出在Java NIO tutorial中看到的一个图片,

a4d35d218235

对于这张图片,我实在是不能苟同其说法.我们可以看到,在这张图片中,我们可以看到,一个线程中只有一个Selector,每个Selector负责监控三个Channel.而实际上,一个线程中,并不是必须只能有一个Selector.一个Selector也不是只能注册三个Channel.

在AbstractSelector的源码中,我们可以看到,实际上它只维护了一个不再监听的Channel的集合:

a4d35d218235

我们查看具体的Selector的父类,SelectorImpl,中的register方法的实现.跟具体的Selector实现相关的类,在JDK提供的src.zip源码包中是找不到的.这里使用CFR反编译器反编译rt.jar包.从中找到其实现.

a4d35d218235

我们可以看到,它会把Channel进一步封装成SelectionKeyImpl.然后使用implRegister方法来实现具体的注册过程.从SelectorImpl的源码中,我们同样可以看到,implRegister方法是一个抽象方法,需要其子类来实现具体的注册过程.

这里我们感兴趣的子类是EPollSelectorImpl,我们查看其源码,可以看到其中维护了一个从file descriptor到SelectionKeyImpl的Map.我们刚刚也提到了,SelectionKeyImpl中,包装了一个Channel,

a4d35d218235

我们从EPollSelectorImpl的implRegister方法中,也没有看到会对Map这个表示EPollSelectorImpl维护的Channel的Map进行尺寸限制的操作.即并没有限制一个EPollSelectorImpl可以注册的Channel的数量.

a4d35d218235

反而是在Channel中,维护了它向Selector注册时,Selector给其返回的SelectionKey的集合.相当于维护了它已经注册的Selector的集合.

a4d35d218235

我们查看AbstractSelectableChannel的向Selector注册的源码:

a4d35d218235

我们可以看到,它会把Selector给它返回的SelectionKey加入到上面我们说过的那个集合中,我们看看addKey()方法的具体实现:

a4d35d218235

在这里我们就可以看到,默认情况下,Channel会创建一个容量为3的表示它注册的Selector的集合.当它需要向更多的Selector注册时,则对这个集合进行扩容.

而并没有提到一个Selector中最多可以注册多少个Channel.

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值