文档章节

jdk的Selector源码分析(一)Selector概述

乒乓狂魔
 乒乓狂魔
发布于 2016/08/16 18:11
字数 799
阅读 313
收藏 0

1系列内容

2 jdk Selector概述

首先来看下文档描述

2.1 创建方式

一个就是直接调用open方法

public static Selector open() throws IOException {
    return SelectorProvider.provider().openSelector();
}

或者调用选用某个SelectorProvider的openSelector

public abstract AbstractSelector openSelector()

2.2 SelectionKey

一个Selector有3种SelectionKey集合

  • 一种就是全部注册的SelectionKey集合,即keys()方法返回的结果

  • 一种就是活跃的SelectionKey集合,即selectedKeys()方法返回的结果

  • 第三种就是已取消的SelectionKey集合,这些已被取消但是还未从Selector取消注册

再确认下下面的几个问题:

  • 什么叫注册

    即将一个channel感兴趣的事件注册到Selector上,即如下方法

    SelectionKey register(AbstractSelectableChannel ch, int ops, Object att)
    

    对于select、poll的Selector实现:仅仅是保存上述AbstractSelectableChannel感兴趣的ops到指定地方

    对于epoll的Selector实现:则是执行系统调用epoll_ctl方法,操作参数是EPOLL_CTL_ADD

  • 什么叫取消

    就是调用SelectionKey的cancel方法,该方法的实现是,将该SelectionKey放入cancelledKeys而已,没有做其他操作

  • 什么叫取消注册

    取消注册,就是从Selector从释放出来不再关注某个事件。通常在我们的select过程中就会遍历上述cancelledKeys,依次执行取消注册的行为。不同的Selector有不同的行为,如epoll则是执行系统调用epoll_ctl方法,操作参数是EPOLL_CTL_DEL。

2.3 三种select方式

分别如下:

int select():表示一直阻塞到有事件为止

int select(long timeout):最多阻塞timeout时间

int selectNow():不阻塞,检查结果后立即返回

2.4 并发性

Selector不是线程安全的,不过大部分情况都是一个线程拥有一个Selector,所以不需要它线程安全。

2.5 使用案例

以ZooKeeper为例,代码简述如下

final Selector selector = Selector.open();

public void run() {
    while (!ss.socket().isClosed()) {
        try {
            selector.select(1000);

            Set<SelectionKey> selected = selector.selectedKeys();

            for (SelectionKey k : selected) {
                if ((k.readyOps() & SelectionKey.OP_ACCEPT) != 0) {

					//执行accept连接的事件

                    SocketChannel sc = ((ServerSocketChannel) k
                            .channel()).accept();
                    sc.configureBlocking(false);
                    SelectionKey sk = sc.register(selector,
                            SelectionKey.OP_READ);
                    NIOServerCnxn cnxn = createConnection(sc, sk);
                    sk.attach(cnxn);
                    addCnxn(cnxn);
                } else if ((k.readyOps() & (SelectionKey.OP_READ | SelectionKey.OP_WRITE)) != 0) {
					
					//执行IO读写事件
					
                    NIOServerCnxn c = (NIOServerCnxn) k.attachment();
                    c.doIO(k);
                } else {
                    //未知
                }
            }
            selected.clear();
        } catch (RuntimeException e) {
            LOG.warn("Ignoring unexpected runtime exception", e);
        } catch (Exception e) {
            LOG.warn("Ignoring exception", e);
        }
    }
    closeAll();
    LOG.info("NIOServerCnxn factory exited run method");
}

while循环里面不断调用selector.select(1000)方法,然后通过selector.selectedKeys()来获取到有事件的SelectionKey集合,即上述提到的活跃的SelectionKey集合。然后遍历该集合,执行对应的事件。

3 不同实现类

目前Selector目前有如下实现

Selector实现类

针对linux平台的实现:

  • PollSelectorImpl:基于poll来实现
  • EPollSelectorImpl:基于epoll来实现

针对windows平台的实现:

  • WindowsSelectorImpl

而Netty的NioEventLoop则是使用上述linux平台的实现PollSelectorImpl。Netty自己提供了另外一种epoll实现,没有直接采用上述jdk自带的EPollSelectorImpl。

4 后续

接下来就要开始重点说说jdk的poll是怎么实现的,即PollSelectorImpl的内容

© 著作权归作者所有

共有 人打赏支持
乒乓狂魔
粉丝 1004
博文 105
码字总数 271356
作品 0
长宁
程序员
NIO 之 Selector实现原理

相关文章 NIO 之 ByteBuffer实现原理 NIO 之 Channel实现原理 BIO、NIO、AIO 内部原理分析 概述 Selector允许单线程处理多个 Channel。如果你的应用打开了多个连接(通道),但每个连接的流量...

轨迹_
06/22
0
0
netty源码分析之揭开reactor线程的面纱(二)

如果你对netty的reactor线程不了解,建议先看下上一篇文章netty源码分析之揭开reactor线程的面纱(一),这里再把reactor中的三个步骤的图贴一下 我们已经了解到netty reactor线程的第一步是...

闪电侠_
08/02
0
0
Netty源码分析(二)EventLoopGroup分析

准备将Netty的源码过一下,一来对自己是个总结消化的过程,二来希望对那些打算看Netty源码的人(已经熟悉Netty的Reactor模型)能有一些帮助。目前所看Netty版本是4.1.3.Final。 1 目录 - Ne...

乒乓狂魔
2016/09/06
421
0
netty源码分析之揭开reactor线程的面纱(一)

netty最核心的就是reactor线程,对应项目中使用广泛的NioEventLoop,那么NioEventLoop里面到底在干些什么事?netty是如何保证事件循环的高效轮询和任务的及时执行?又是如何来优雅地fix掉jdk...

闪电侠_
07/31
0
0
java bio,nio,aio及源码

版权声明:本文为博主原创文章,未经博主允许不得转载。 目录(?)[+] NIO 简介 随着JavaIO类库的不断发展和改进,基于Java的网络编程会变得越来越简单。随着异步IO功能的增强,基于JavaNIO开发...

onedotdot
2017/10/20
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Hbase Schema 模型设计注意事项及示例

一、Hbase 数据模型概述 HBase的数据模型也是由表组成,每一张表里也有数据行和列,但是在HBase数据库中的行和列又和关系型数据库的稍有不同。 表(Table): HBase会将数据组织成一张表,表名必...

PeakFang-BOK
37分钟前
1
0
Blockathon(2018)上海竞赛项目成果今天揭晓

开幕式现场 10月19日,Blockathon(2018)上海在黄浦区P2联合创业办公社举行,本次活动由50名区块链开发者组成9支参赛队伍,来自国内外优秀区块链开发团队的20名技术专家担任导师及裁判。9支队...

HiBlock
40分钟前
0
0
微信小程序开发系列六:微信框架API的调用

微信小程序开发系列教程 微信小程序开发系列一:微信小程序的申请和开发环境的搭建 微信小程序开发系列二:微信小程序的视图设计 微信小程序开发系列三:微信小程序的调试方法 微信小程序开发...

JerryWang_SAP
今天
4
0
5 个用 Python 编写 web 爬虫的方法

大家在读爬虫系列的帖子时常常问我怎样写出不阻塞的爬虫,这很难,但可行。通过实现一些小策略可以让你的网页爬虫活得更久。那么今天我就将和大家讨论这方面的话题。 我刚整理了一套2018最新...

糖宝lsh
今天
6
0
docker安装redis、mongodb、mysql等

一、启动docker服务,设置镜像: systemctl start dockervi /etc/docker/daemon.json{ "registry-mirrors": ["https://registry.docker-cn.com"]} 二、下拉镜像: 在镜像中心h...

狼王黄师傅
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部