选择器(Selector) 是 SelectableChannle 对象的多路复用器,Selector 可以同时监控多个 SelectableChannel 的 IO 状况,也就是说,利用 Selector可使一个单独的线程管理多个 Channel,selector 是非阻塞 IO 的核心。

SelectableChannle 的继承树如下图:

选择器(Selector)的应用:

当通道使用register(Selector sel, int ops)方法将通道注册选择器时,选择器对通道事件进行监听,通过第二个参数指定监听的事件类型。

其中可监听的事件类型包括以下:

  读 : SelectionKey.OP_READ (1)

  写 : SelectionKey.OP_WRITE (4)

  连接 : SelectionKey.OP_CONNECT (8)

  接收 : SelectionKey.OP_ACCEPT (16)

如果需要监听多个事件是:

  int key = SelectionKey.OP_READ | SelectionKey.OP_WRITE ; //表示同时监听读写操作

如何应用请看代码:

public class NIOBlocking2 {

   //客户端
@Test
public void client() throws Exception {
//1. 获取socketChannel
SocketChannel sChannel = SocketChannel.open();
//2. 创建连接
sChannel.connect(new InetSocketAddress("127.0.0.1", 9898));
ByteBuffer buf = ByteBuffer.allocate(1024);
//3. 设置通道为非阻塞
sChannel.configureBlocking(false); @SuppressWarnings("resource")
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
String msg = scanner.nextLine(); buf.put((new Date() + ":" + msg).getBytes());
buf.flip();
//4. 向通道写数据
sChannel.write(buf);
buf.clear();
}
}

   //服务端
@Test
public void server() throws Exception {
//1. 获取服务端通道
ServerSocketChannel ssChannel = ServerSocketChannel.open();
ssChannel.bind(new InetSocketAddress(9898));
//2. 设置为非阻塞模式
ssChannel.configureBlocking(false); //3. 打开一个监听器
Selector selector = Selector.open();
//4. 向监听器注册接收事件
ssChannel.register(selector, SelectionKey.OP_ACCEPT); while (selector.select() > 0) {
//5. 获取监听器上所有的监听事件值
Iterator<SelectionKey> it = selector.selectedKeys().iterator(); //6. 如果有值
while (it.hasNext()) {
//7. 取到SelectionKey
SelectionKey key = it.next(); //8. 根据key值判断对应的事件
if (key.isAcceptable()) {
//9. 接入处理
SocketChannel socketChannel = ssChannel.accept();
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
} else if (key.isReadable()) {
//10. 可读事件处理
SocketChannel channel = (SocketChannel) key.channel();
readMsg(channel);
}
//11. 移除当前key
it.remove();
}
}
} private void readMsg(SocketChannel channel) throws IOException {
ByteBuffer buf = ByteBuffer.allocate(1024);
int len = 0;
while ((len = channel.read(buf)) > 0) {
buf.flip();
byte[] bytes = new byte[1024];
buf.get(bytes, 0, len);
System.out.println(new String(bytes, 0, len));
}
} }

NIO的非阻塞性:

nio的非阻塞是对于网络通道来说的,需要使用Channel.configureBlocking(false)来设置通道为非阻塞的,如果没设置,默认是阻塞的。

Java NIO (四) 选择器(Selector)的更多相关文章

  1. Java NIO之选择器Selector

    在单独的线程中,检查多个通道是否可以进行IO操作. Selector创建:静态工厂方法创建 Selector selector = Selector.open(); 注册通道 channel.conf ...

  2. 【NIO】Java NIO之选择器

    一.前言 前面已经学习了缓冲和通道,接着学习选择器. 二.选择器 2.1 选择器基础 选择器管理一个被注册的通道集合的信息和它们的就绪状态,通道和选择器一起被注册,并且选择器可更新通道的就绪状态,也可 ...

  3. java输入输出 -- Java NIO之选择器

    一.简介 前面的文章说了缓冲区,说了通道,本文就来说说 NIO 中另一个重要的实现,即选择器 Selector.在更早的文章中,我简述了几种 IO 模型.如果大家看过之前的文章,并动手写过代码的话.再 ...

  4. Java NIO:选择器

    最近打算把Java网络编程相关的知识深入一下(IO.NIO.Socket编程.Netty) Java NIO主要需要理解缓冲区.通道.选择器三个核心概念,作为对Java I/O的补充, 以提升大批量数 ...

  5. Java NIO之选择器

    1.简介 前面的文章说了缓冲区,说了通道,本文就来说说 NIO 中另一个重要的实现,即选择器 Selector.在更早的文章中,我简述了几种 IO 模型.如果大家看过之前的文章,并动手写过代码的话.再 ...

  6. 7. 彤哥说netty系列之Java NIO核心组件之Selector

    --日拱一卒,不期而至! 你好,我是彤哥,本篇是netty系列的第七篇. 简介 上一章我们一起学习了Java NIO的核心组件Buffer,它通常跟Channel一起使用,但是它们在网络IO中又该如何 ...

  7. Java NIO学习系列三:Selector

    前面的两篇文章中总结了Java NIO中的两大基础组件Buffer和Channel的相关知识点,在NIO中都是通过Channel和Buffer的协作来读写数据的,在这个基础上通过selector来协调 ...

  8. Java NIO学习系列四:NIO和IO对比

    前面的一些文章中我总结了一些Java IO和NIO相关的主要知识点,也是管中窥豹,IO类库已经功能很强大了,但是Java 为什么又要引入NIO,这是我一直不是很清楚的?前面也只是简单提及了一下:因为性 ...

  9. Java NIO (转)

    Java NIO提供了与标准IO不同的IO工作方式: Channels and Buffers(通道和缓冲区):标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(B ...

  10. 【转】java NIO 相关知识

    原文地址:http://www.iteye.com/magazines/132-Java-NIO Java NIO(New IO)是从Java 1.4版本开始引入的一个新的IO API,可以替代标准的 ...

随机推荐

  1. Spring JDBC(一)jdbcTemplate

    前言 最近工作中经常使用Spring JDBC操作数据库,也断断续续的看了一些源码,便有了写一些总结的想法,希望在能帮助别人的同时,也加深一下自己对Spring JDBC的理解. Spring JDB ...

  2. FFmpeg之AVPacket

    花满楼原创 AVPacket,是压缩数据的结构体(解码前或编码后的结构体). 本文介绍FFmepg中常见结构AVPacekt,尽量用具体值来理解. 整个用于调试的代码可以这样写: #include & ...

  3. 高质量PHP代码的50个实用技巧必备(上)

    1.不要使用相对路径 常常会看到: ? 1 require_once('../../lib/some_class.php'); 该方法有很多缺点: 它首先查找指定的php包含路径, 然后查找当前目录. ...

  4. java 接口测试

    学习java 时间也不算太长,大学有点基础,学起来也顺手多了,其实我感觉更是因为学习完python之后,在学习别的语言的时候就简单多了,几乎所有的语言学起来都差不多.前几篇写过的都是python接口测 ...

  5. YiShop_商城网站建设应该注意什么

    现在电子商务迅速发展,而专门搭建商城网站的第三方开发商也很多.现在搭建一个商城网站容易,如何运营一个商城网站才是重点.下面就由YiShop说说电子商城网站建设要思考什么呢(1)建设网站的目的是什么首先 ...

  6. 深入浅出了解frame和bounds

    frame frame的官方解释如下: The frame rectangle, which describes the view's location and size in its supervi ...

  7. Java爬虫——B站弹幕爬取

    如何通过B站视频AV号找到弹幕对应的xml文件号 首先爬取视频网页,将对应视频网页源码获得 就可以找到该视频的av号aid=8678034 还有弹幕序号,cid=14295428 弹幕存放位置为  h ...

  8. [源码]解析 SynchronousQueue 上界,下界.. 数据保存和数据传递. 堵塞队列. 有无频繁await?

     简析SynchronousQueue.LinkedBlockingQueue(两个locker,更快),ArrayBlockingQueue(一个locker,读写都竞争)     三者都是bloc ...

  9. 用泛型创建SqlServerHelper类实现增删改查(一)

    使用泛型,可以构建对数据库单表的基本增删改查. 首先有一数据库 Test_SqlServerHelper ,有2表 接下来创建项目,对数据库进行增删改查. 直接贴代码:(SqlServerHelper ...

  10. zephyr初始化流程

    1.调用应用层main()函数         kernel/init.c      181行 /** * * @brief Mainline for kernel's background task ...