zoukankan      html  css  js  c++  java
  • 【原创】java NIO selector 学习笔记 一

    能力有限,仅仅是自己看源码的一些笔记。

    主要介绍 可选通道 和 选择器 选择键(SelectableChannel  和 Selector SelectionKey)

          选择器(Selector) 选择器类管理着一个被注册的通道集合的信息和它们的就绪状态。通道是和选择器一起被注册的,并且使用选择器来更新通道的就绪状态。当这么做的时候,可以选择将被激发的线程挂起,直到有就绪的的通道。

          可选通道 selectableChannel可以被注册到Selector对象上,一个通道可以被注册到多个选择器上,但是对于每个选择器而言只能被注册一次。而且只有继承了selectableChannel的类才能被注册到通道上,并且注册的Channel需要是非阻塞的。

      选择键 选择键封装了特定的通道与特定的选择器的注册关系。

      接下来结合socketChannel的代码一一介绍:

      serverSocketChannel = ServerSocketChannel.open();
      serverSocketChannel.socket().bind(new InetSocketAddress(port));
      serverSocketChannel.configureBlocking(false);

      selector = Selector.open();

      

    while(true)
    {
    SocketChannel socketchannel =serverSocketChannel.accept();
    if(socketchannel!=null)
    {
    System.out.println("收到连接");
    socketchannel.configureBlocking(false);
    socketchannel.register(selector, SelectionKey.OP_READ);

    }
    int num=selector.selectNow();
    if(num>0)
    {
    Set selectedKeys = selector.selectedKeys();
    Iterator keyItertor=selectedKeys.iterator();
    while(keyItertor.hasNext())
    {
    SelectionKey key = (SelectionKey) keyItertor.next();
    if(key.isReadable())
    {
    socketchannel = (SocketChannel) key.channel();

    System.out.println(new String(buffer.array(),"utf-8"));
    buffer.clear();
    break;
    }
    }
    }
    }

     首先获取一个Selector。获取selector只能使用Open方法。接下来我想说的是注册 register方法

      Channel的register的源码 来自AbstractSelectableChannel

    public final SelectionKey register(Selector sel, int ops,
    Object att)
    throws ClosedChannelException
    {
    if (!isOpen())
    throw new ClosedChannelException();
    if ((ops & ~validOps()) != 0)
    throw new IllegalArgumentException();
    synchronized (regLock) {
    if (blocking)
    throw new IllegalBlockingModeException();
    SelectionKey k = findKey(sel);
    if (k != null) {
    k.interestOps(ops);
    k.attach(att);
    }
    if (k == null) {
    // New registration
    k = ((AbstractSelector)sel).register(this, ops, att);
    addKey(k);
    }
    return k;
    }
    }

     当这个Channel已经在通道上注册了的话则更新 ops和att,否则调用AbstractSelector的register方法来注册。注意 Selector本身并没有register方法。

    然后再看SelectorImp中的实现:

    protected final SelectionKey register(AbstractSelectableChannel ch,
    int ops,
    Object attachment)
    {
    if (!(ch instanceof SelChImpl))
    throw new IllegalSelectorException();
    SelectionKeyImpl k = new SelectionKeyImpl((SelChImpl)ch, this);
    k.attach(attachment);
    synchronized (publicKeys) {
    implRegister(k);
    }
    k.interestOps(ops);
    return k;
    }

     implRegister()的实现没找到。对于SPI不了解呀。

    接下来介绍SelectionKey

    介绍SelectionKeyImp

    成员:

    final SelChImpl channel; // package-private
    final SelectorImpl selector; // package-private

    // Index for a pollfd array in Selector that this key is registered with
    private int index;

    private volatile int interestOps;
    private int readyOps;

    和注册相关的方法:

    public SelectionKey interestOps(int ops) {
    ensureValid();
    return nioInterestOps(ops);
    }

    SelectionKey nioInterestOps(int ops) { // package-private
    if ((ops & ~channel().validOps()) != 0)
    throw new IllegalArgumentException();
    channel.translateAndSetInterestOps(ops, this);
    interestOps = ops;
    return this;
    }

    这一篇就到这吧。

  • 相关阅读:
    CSS学习1
    三个和尚没水喝阅读笔记
    Javascript学习1

    mv 批量
    emacs 大小写转换
    too many open files
    成都定房
    有关重定向
    postgresql 数据库
  • 原文地址:https://www.cnblogs.com/earendil/p/5024226.html
Copyright © 2011-2022 走看看