【Netty学习与理解】BIO&NIO

先来熟悉一下阻塞与非阻塞的概念,二者关注的是等待程序调用结果时的状态。

  • 阻塞,指程序返回调用结果之前,当前线程会被挂起。
  • 非阻塞,程序返回调用结果之前,线程不会被挂起,可以用过轮询或者回调的方法获取返回结果。

BIO

实现

ServerSocket serverSocket = new ServerSocket(9000);

事件处理

Socket accept = serverSocket.accept();

accept()会阻塞,其原理是调用了一个native的方法socketAccept(),该方法对应JVM中的PlainSocketImpl.c中的Java_java_net_PlainSocketImpl_socketAccept()方法,猜测JVM是通过Linux底层的pthread_mutex_lock和pthread_mutex_unlock来实现阻塞与解阻塞。
在这里插入图片描述

缺点

accep()是阻塞的,当处理一个客户端请求时,服务端是没有办法再响应其他客户端的请求。如果对每个客户端都开启一个线程异步的处理,但线程的数量是无法预估的,出现C10k问题将会给服务器带来很大的压力。

NIO

实现(不使用Reactor模型)

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

事件处理

SocketChannel socketChannel = serverSocketChannel.accept();

ServerSocketChannel的accept()方法是非阻塞的,此时可以通过不断的轮询看是否有事件发生,一旦有事件发生,并不会直接处理,而是放到一个list中,统一进行处理。

缺点

这种方式也会出现C10k问题,因为要遍历放了SocketChannel的list,而这个list中并不是每个Channel都有事件发生,所以在遍历时会产生多余的开销。

实现(使用Reactor模型)

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.socket().bind(new InetSocketAddress(9000));
serverSocketChannel.configureBlocking(false);
Selector selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

事件处理

selector.select();
Set<SelectionKey> selectionKeys = selector.selectedKeys();

这里会阻塞等待事件的发生,并且只关心那些有事件发生的Channel。

NIO三大核心组件

  • Channel
  • Buffer
  • Selector
    Channel,类似于流,每个Channel对应一个Buffer,Buffer底层是一个数组。
    channel会注册到selector上,由selector根据channel读写事件的发生将其交由某个空闲的线程处理。
    NIO的channel和buffer都是既可读又可写。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值