前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java的nio是水平触发吗

java的nio是水平触发吗

作者头像
平凡的学生族
发布2019-05-25 08:53:03
8130
发布2019-05-25 08:53:03
举报
文章被收录于专栏:后端技术后端技术

java的nio是水平触发吗?在linux上,其实现是基于linux epoll的。所以首先我们要了解epoll。

epoll 水平触发

epoll 水平触发与边缘触发一文中讲述了水平触发的条件:

  1. 对于读操作 只要缓冲内容不为空,LT模式返回读就绪。
  2. 对于写操作 只要缓冲区还不满,LT模式会返回写就绪。

所以,Linux epoll的水平触发是以缓冲区空满状态来判断的

那java nio是水平触发吗

首先我们知道了,Linux epoll的水平触发是以缓冲区空满状态来判断的。 所以,验证java nio水平触发的办法是客户端写多个字节(比如1000个),服务端每次都不读取字节,缓冲区一直没读完,处于非空状态。由于水平触发,读事件应当会一直触发。 如果能多次触发读事件,就应当是水平触发,我们用以下代码验证: 在下列代码中:

  • 客户端发送"hello world"后即停止运行。
  • 服务端会处理连接事件,但对读事件不会做任何处理,使得读取缓冲区始终非空。

服务端:

代码语言:javascript
复制
public class NioServer {
    public static void main(String[] argv) throws Exception {
        Selector selector = Selector.open();
        ServerSocketChannel server = ServerSocketChannel.open();
        server.bind(new InetSocketAddress("0.0.0.0", 1339));
        server.configureBlocking(false);
        server.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            int n = selector.select();
            if (n == 0) continue;

            System.out.println("Select " + n);

            Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
            while (keys.hasNext()) {
                SelectionKey key = keys.next();
                keys.remove();
                if (key.isAcceptable()) {
                    ServerSocketChannel channel = (ServerSocketChannel) key.channel();
                    SocketChannel accept = channel.accept();
                    accept.configureBlocking(false);
                    accept.register(selector, SelectionKey.OP_READ);
                } else if (key.isReadable()) {
                    SocketChannel channel = (SocketChannel) key.channel();

                    // 不读取任何数据
                }
            }
            System.out.println("休眠一秒, 减缓输出, 便于观察");
            Thread.sleep(1000);
        }
    }
}

客户端:

代码语言:javascript
复制
public class NioClient
{
    private static SocketChannel socketChannel = null;

    private static Charset charset = Charset.forName("GBK");

    public static void init() throws IOException
    {
        socketChannel = SocketChannel.open();
        InetAddress ia = InetAddress.getLocalHost();
        InetSocketAddress isa = new InetSocketAddress(ia, 1339);
        socketChannel.connect(isa);
        socketChannel.configureBlocking(false);
        System.out.println("与服务器的连接建立成功!");
    }
    
    public static void main(String[] args) throws InterruptedException, IOException {
        init();
        socketChannel.write(charset.encode("hello world"));
    }

}

输出

客户端

服务端

现象

  • 客户端发送"hello world"后即结束运行。
  • 服务端始终没读取字节,缓冲区非空。即使调用了keys.remove();删除key,在之后的循环中依旧会一直触发读取事件

结论

只要缓冲区非空,就能一直触发读取事件。所以linux中,java nio是水平触发的

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.04.26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • epoll 水平触发
  • 那java nio是水平触发吗
  • 结论
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档