Java NIO学习笔记-Selector

Selector选择器是什么

Selector(选择器)是Java NIO中能够检测一到多个NIO通道,并能够知晓通道是否为诸如读写事件做好准备的组件。这样,一个单独的线程可以管理多个channel,从而管理多个网络连接。

Java NIO的选择器部分,实际上有三个重要的类:

  • Selector 选择器,完成主要的选择功能,维护着注册的一组SelectionKey。
  • SelectableChannel 记录了一组注册的SelectionKey[]。
  • SelectionKey 关联了一个Channel和一个Selector,描述一个Selector和SelectableChannel的关系。并保存有通道所关心的操作。
Selector

更新准备好的SelectionKey,移除isValid()为false的SelectionKey

  • select() //阻塞等待,直至一个channel准备好或调用wakeup()才返回
  • select(long timeout) //如上,返回条件多了个超时时间
  • selectNow() //非阻塞,会立刻返回,没有时返回值=0
  • wakeup() //使得Selector返回
SelectionKey

兴趣操作集,通过它就可以知道channel可以去做哪些事了.有4种类型,如下:

  • public static final int OP_READ = 1 << 0;
  • public static final int OP_ACCEPT = 1 << 4;
  • public static final int OP_WRITE = 1 << 2;
  • public static final int OP_CONNECT = 1 << 3;
    通过SelectionKey.interestOps(int ops)就可以配置这些值
SelectionKey
  • SelectionKey.attach(Object ob) //添加附件,另一种方式SelectableChannel.register(Selector sel, int ops, Object att)
  • SelectionKey.attachment() //获取附件
  • SelectionKey.cancel(),永久的注销键,加入Selector的注销集中,在下次select()时被移除
完整实例
@Test
public void client() throws IOException {
    //获取通道
    SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 7777));
    //切换成非阻塞模式
    socketChannel.configureBlocking(false);
    //分配缓冲区
    ByteBuffer buffer = ByteBuffer.allocate(1024);
    //发送数据给服务端
    Scanner scanner = new Scanner(System.in);
    while (scanner.hasNext()) {
        String str = scanner.next();
        buffer.put((LocalDateTime.now().toString().getBytes() + ":" + str).getBytes());
        buffer.flip();
        socketChannel.write(buffer);
        buffer.clear();
    }
    //关闭通道
    socketChannel.close();
}

@Test
public void server() throws IOException {
    //获取通道
    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    //切换非阻塞模式
    serverSocketChannel.configureBlocking(false);
    //绑定连接
    serverSocketChannel.bind(new InetSocketAddress(7777));
    //获取选择器
    Selector selector = Selector.open();
    //将通道注册到选择器
    //可以监听的事件类型
    //读 SelectionKey.OP_READ  1
    //写 SelectionKey.OP_WRITE 4
    //连接 SelectionKey.OP_CONNECT  8
    //接收SelectionKey.OP_ACCEPT 16
    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
    //轮询获取选择器上已经准备就绪的事件
    while (selector.select() > 0) {
        //获取当前选择器中所有注册的选择键(已就绪的监听事件)
        Set<SelectionKey> selectedKeys = selector.selectedKeys();
        Iterator<SelectionKey> iterator = selectedKeys.iterator();
        while (iterator.hasNext()) {
            //获取准备就绪的事件
            SelectionKey selectionKey = (SelectionKey) iterator.next();
            //判断具体是什么事件准备就绪
            if (selectionKey.isAcceptable()) {
                //若接收就绪,就获取客户端的连接
                SocketChannel socketChannel = serverSocketChannel.accept();
                //切换非阻塞模式
                socketChannel.configureBlocking(false);
                //将该通道注册到选择器上
                socketChannel.register(selector, SelectionKey.OP_READ);
            } else if (selectionKey.isReadable()) {
                //若读就绪,获取当前选择器上读就绪状态的通道
                SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                //读取数据
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                int length = 0;
                while ((length = socketChannel.read(buffer)) > 0) {
                    buffer.flip();
                    System.out.println(new String(buffer.array(), 0, length));
                    buffer.clear();
                }
            }
            //取消选择键 SelectionKey
            iterator.remove();
        }
    }
}

参考:http://www.cnblogs.com/bronte/articles/1966550.html
http://ifeve.com/selectors/

代码托管:https://git.oschina.net/umgsai/java-nio

转载于:https://www.cnblogs.com/umgsai/p/6684091.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值