博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java NIO (四) 选择器(Selector)
阅读量:5274 次
发布时间:2019-06-14

本文共 3025 字,大约阅读时间需要 10 分钟。

选择器(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
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)来设置通道为非阻塞的,如果没设置,默认是阻塞的。

转载于:https://www.cnblogs.com/qq-361807535/p/6670529.html

你可能感兴趣的文章
字符串方法title()、istitle()
查看>>
yield语句
查看>>
java序列化问题
查看>>
Html.Partial和Html. RenderPartial用法
查看>>
查看linux系统中占用cpu最高的语句
查看>>
[洛谷P1738]洛谷的文件夹
查看>>
Ubuntu server 16.04的安装 以及配置(服务器版)
查看>>
Jtest 对象库的使用(Object Repository)
查看>>
phpstudy的mysql版本升级至5.7
查看>>
ubuntu server设置时区和更新时间
查看>>
《弟子规》下的沉思
查看>>
B. Beautiful Paintings
查看>>
AtCoder Beginner Contest 103
查看>>
Codeforces 589F Gourmet and Banquet
查看>>
随机字符串。
查看>>
Create参数为:nil/self/application的区别
查看>>
网络流24题 飞行员配对方案问题
查看>>
STM32空闲中断
查看>>
Python 直接赋值、浅拷贝和深度拷贝解析
查看>>
剑指offer python版 调整数组顺序使奇数位于偶数前面
查看>>