您当前的位置: 首页 >  nio

恐龙弟旺仔

暂无认证

  • 0浏览

    0关注

    282博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

NIO源码解析-Selector

恐龙弟旺仔 发布时间:2021-09-22 18:58:50 ,浏览量:0

前言:

    有关于Selector的使用,我们在之前的示例中就已经用到过了。当然,基本都是最简单的使用。而有关于Selector的其他API、SelectionKey的API,我们都没有详细介绍过。故单独列一篇,来说明下其使用。

1.Selector的创建与使用
// 创建,创建比较简单,就是一句话,实际后面做了很多工作。
Selector selector = Selector.open();

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

// SelectorProvider.provider()
public static SelectorProvider provider() {
    synchronized (lock) {
        if (provider != null)
            return provider;
        return AccessController.doPrivileged(
            new PrivilegedAction() {
                public SelectorProvider run() {
                    // 加载java.nio.channels.spi.SelectorProvider系统参数配置对应的Provider
                    if (loadProviderFromProperty())
                        return provider;
                    // SPI方式加载SelectorProvider实现类
                    if (loadProviderAsService())
                        return provider;
                    // 以上两种都没有,则返回默认provider。
                    // 笔者Windows系统下直接返回WindowsSelectorProvider
                    // 最终Selector为WindowsSelectorImpl
                    provider = sun.nio.ch.DefaultSelectorProvider.create();
                    return provider;
                }
            });
    }
}
可以看到,Selector还是提供了很多方式来供我们选择Provider的。
1.1 select
    之前的文章中,展示了select方法的使用,Selector还有其他select类型方法
// 获取哪些已经准备好的channel数量。非阻塞,方法会立即返回
public abstract int selectNow() throws IOException;

// 同selectNow,会一直阻塞到有准备好的channel事件为止
public abstract int select() throws IOException;

// 同select(),会阻塞最多timeout毫秒后返回
public abstract int select(long timeout)

    我们可以在使用中选择合适的select方法,避免长时间的线程阻塞。

1.2 wakeup

    Selector提供wakeup方法来唤醒阻塞在1.1中select方法中的线程。

/**
     * Causes the first selection operation that has not yet returned to return
     * immediately.
     *
     * 

If another thread is currently blocked in an invocation of the * {@link #select()} or {@link #select(long)} methods then that invocation * will return immediately. If no selection operation is currently in * progress then the next invocation of one of these methods will return * immediately unless the {@link #selectNow()} method is invoked in the * meantime. In any case the value returned by that invocation may be * non-zero. Subsequent invocations of the {@link #select()} or {@link * #select(long)} methods will block as usual unless this method is invoked * again in the meantime. * *

Invoking this method more than once between two successive selection * operations has the same effect as invoking it just once.

* * @return This selector */ public abstract Selector wakeup();

注解真的很全了。

如果当前线程阻塞在select方法上,则立即返回;

如果当前Selector没有阻塞在select方法上,则本次wakeup调用会在下一次select方法阻塞时生效;

1.3 close
public abstract void close() throws IOException;
public abstract boolean isOpen();

    当我们不再使用Selector时,需要调用close方法来释放掉其它占用的资源,并将所有相关的选择键设置为无效。

    被close后的Selector则不能再使用。

    同时提供了isOpen方法来检测Selector是否开启。

1.4 keys & selectedKeys
// Returns this selector's key set.
public abstract Set keys();

// Returns this selector's selected-key set.
public abstract Set selectedKeys();

keys方法返回的是目前注册到Selector上的所有channel以及对应事件;

selectedKeys方法返回的是目前注册到Selector上的所有channel活跃的事件。返回的结果集的每个成员都被判定是已经准备好了。

故,我们之前一直使用的就是selectedKeys方法。

那么SelectionKey是什么呢?接着看。

2.SelectionKey
// A token representing the registration of 
// a {@link SelectableChannel} with a {@link Selector}.
public abstract class SelectionKey {
    
    // 代表我们关注的4种事件
    public static final int OP_READ = 1             
关注
打赏
1655041699
查看更多评论
0.7867s