java nio之selector源码探究

我不生产知识,我只是知识的搬运工。努力通过实践与各位博友交流一些自己的见解。

java nio的相关概念:

Buffer

与channel相连接,从channel中读入和读出数据时都需要缓存,加快数据读取和填充速度。常用的为ByteBuffer,其他的还包括LongBuffer,IntBuffer以及DoubleBuffer等等。一张图示:

Channel

Java NIO channel类似于流,但有一些区别:

  1.你可以读和写一个channel。流通常是单向的(读或写)。

  2.channel可以异步读写。

  3.channel总是读取或写入缓冲区。并将数据从一个缓冲区写入上述通道。

Selector

selector可用于非阻塞I/O操作。selector是监视事件的多个channel的对象。当java nio执行非阻塞IO操作时,selector和带有可选channel的选择键定义了多路IO操作。因此,简单地说,我们可以说selector用于选择准备好进行I/O操作的channel。selector用于监视多个channel中的就绪事件。从而一个selector线程就能处理多个网络连接。

 

 

 实践代码

上一篇文章java的nio 之 select,poll和epoll理论知识 从操作系统的c语言层面来讲解nio的实现,包括select,poll和epoll他们的区别和使用场景。这篇文章将继续深入探究java 的nio到底层jvm的实现,从而将两者联系起来。先通过时序图有一个总的概括认识:

 

严格来说,我这个只能算是个草图。哈哈哈,第一次画还请各位多多担待。从源码来看selector实现,windows最终调用的select系统调用,而linux最终调用的epoll系统调用。

从小白看源码的角度来提几点注意事项,大佬勿喷。

1.如果是用windows的idea来追踪源码,那么linux这条线需要自己从openjdk上下载代码来看。

2.关于linux的SelectorProvider的选择,solaris\classes\sun\nio\ch

    public static SelectorProvider create() {
        String osname = AccessController
            .doPrivileged(new GetPropertyAction("os.name"));
        if (osname.equals("SunOS"))
            return createProvider("sun.nio.ch.DevPollSelectorProvider");
        if (osname.equals("Linux"))
            return createProvider("sun.nio.ch.EPollSelectorProvider");
        return new sun.nio.ch.PollSelectorProvider();
    }
View Code

3.如果是追踪到native方法,就需要到openjdk代码中查看c类型的代码,如EpollArrayWrapper中的native int epollWait。solaris\native\sun\nio\ch\EPollArrayWrapper.c

java的类名和c语言的类名是一一对应的。

JNIEXPORT jint JNICALL
Java_sun_nio_ch_EPollArrayWrapper_epollWait(JNIEnv *env, jobject this,
                                            jlong address, jint numfds,
                                            jlong timeout, jint epfd)
{
    struct epoll_event *events = jlong_to_ptr(address);
    int res;

    if (timeout <= 0) {           /* Indefinite or no wait */
        RESTARTABLE(epoll_wait(epfd, events, numfds, timeout), res);
    } else {                      /* Bounded wait; bounded restarts */
        res = iepoll(epfd, events, numfds, timeout);
    }

    if (res < 0) {
        JNU_ThrowIOExceptionWithLastError(env, "epoll_wait failed");
    }
    return res;
}
View Code

 

 

个人认为有效的学习应该是成系统的,有个人思考和输出的!所以后续还会更新nio实现高效网络框架netty的相关文章。
附上nio的一些基础教程:

https://www.geeksforgeeks.org/introduction-to-java-nio-with-examples/

http://tutorials.jenkov.com/java-nio/index.html

posted @ 2021-01-01 08:48  老汤的猫  阅读(198)  评论(0编辑  收藏  举报