一、问题

BIO 和 NIO 作为 Server 端,当建立了 10 个连接时,分别产生多少个线程?

答案: 因为传统的 IO 也就是 BIO 是同步线程堵塞的,所以每个连接都要分配一个专用线程来处理请求,这样 10 个连接就会创建 10 个线程去处理。而 NIO 是一种同步非阻塞的 I/O 模型,它的核心技术是多路复用,可以使用一个链接上的不同通道来处理不同的请求,所以即使有 10 个连接,对于 NIO 来说,开启 1 个线程就够了。

二、BIO 代码实现

public class DemoServer extends Thread {private ServerSocket serverSocket;public int getPort() {return  serverSocket.getLocalPort();}public void run() {try {serverSocket = new ServerSocket(0);while (true) {Socket socket = serverSocket.accept();RequestHandler requestHandler = new RequestHandler(socket);requestHandler.start();}} catch (IOException e) {e.printStackTrace();} finally {if (serverSocket != null) {try {serverSocket.close();} catch (IOException e) {e.printStackTrace();}}}}public static void main(String[] args) throws IOException {DemoServer server = new DemoServer();server.start();try (Socket client = new Socket(InetAddress.getLocalHost(), server.getPort())) {BufferedReader bufferedReader = new BufferedReader(new                   InputStreamReader(client.getInputStream()));bufferedReader.lines().forEach(s -> System.out.println(s));}}}
// 简化实现,不做读取,直接发送字符串
class RequestHandler extends Thread {private Socket socket;RequestHandler(Socket socket) {this.socket = socket;}@Overridepublic void run() {try (PrintWriter out = new PrintWriter(socket.getOutputStream());) {out.println("Hello world!");out.flush();} catch (Exception e) {e.printStackTrace();}}}
  • 服务器端启动 ServerSocket,端口 0 表示自动绑定一个空闲端口。
  • 调用 accept 方法,阻塞等待客户端连接。
  • 利用 Socket 模拟了一个简单的客户端,只进行连接、读取、打印。
  • 当连接建立后,启动一个单独线程负责回复客户端请求。

这样,一个简单的 Socket 服务器就被实现出来了。

(图片来源于杨晓峰)

三、NIO 代码实现

public class NIOServer extends Thread {public void run() {try (Selector selector = Selector.open();ServerSocketChannel serverSocket = ServerSocketChannel.open();) {// 创建 Selector 和 ChannelserverSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(), 8888));serverSocket.configureBlocking(false);// 注册到 Selector,并说明关注点serverSocket.register(selector, SelectionKey.OP_ACCEPT);while (true) {selector.select();// 阻塞等待就绪的 Channel,这是关键点之一Set<SelectionKey> selectedKeys = selector.selectedKeys();Iterator<SelectionKey> iter = selectedKeys.iterator();while (iter.hasNext()) {SelectionKey key = iter.next();// 生产系统中一般会额外进行就绪状态检查sayHelloWorld((ServerSocketChannel) key.channel());iter.remove();}}} catch (IOException e) {e.printStackTrace();}}private void sayHelloWorld(ServerSocketChannel server) throws IOException {try (SocketChannel client = server.accept();) {          client.write(Charset.defaultCharset().encode("Hello world!"));}}// 省略了与前面类似的 main
}
  • 首先,通过 Selector.open() 创建一个 Selector,作为类似调度员的角色。
  • 然后,创建一个 ServerSocketChannel,并且向 Selector 注册,通过指定 SelectionKey.OP_ACCEPT,告诉调度员,它关注的是新的连接请求。注意:为什么我们要明确配置非阻塞模式呢?这是因为阻塞模式下,注册操作是不允许的,会抛出 IllegalBlockingModeException 异常。
  • Selector 阻塞在 select 操作,当有 Channel 发生接入请求,就会被唤醒。
  • 在 sayHelloWorld 方法中,通过 SocketChannel 和 Buffer 进行数据操作,在本例中是发送了一段字符串。

可以看到,在前面两个样例中,IO 都是同步阻塞模式,所以需要多线程以实现多任务处理。而 NIO 则是利用了单线程轮询事件的机制,通过高效地定位就绪的 Channel,来决定做什么,仅仅 select 阶段是阻塞的,可以有效避免大量客户端连接时,频繁线程切换带来的问题,应用的扩展能力有了非常大的提高。下面这张图对这种实现思路进行了形象地说明。

(图片来源于杨晓峰)

四、参考资料

Java核心36讲

近期热门文章

Java 最常见的 200+ 面试题

如果你喜欢本文,扫描二维码关注微信公众号「王磊的博客」

阿里面试题BIO和NIO数量问题附答案和代码相关推荐

  1. 内核aio_Java面试题BIO、NIO、AIO有什么区别?

    点击上方"千锋Java学院",选择"置顶公众号" 每天一道面试模拟真题及解析 课前导读 ●回复"每日一练"获取以前的题目,持续更新! ●我希 ...

  2. Java面试题总结 - Java集合篇(附答案)

    目录 一.Java 容器都有哪些? 二.Collection 和 Collections 有什么区别? 三.list与Set区别 四.HashMap 和 Hashtable 有什么区别? 五.说一下 ...

  3. 常见Java面试题 BIO、NIO、AIO 有什么区别?

    BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低. NIO:New IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通 ...

  4. 携程测试经理网盘爆出面试题!!!【内附答案】

    这将有助于行业新人,以及想要切换当前工作的测试专业人士!!! 首先,你需要了解有关软件测试的内容! 第一个基本的东西 - 测试概念:你需要非常擅长这一点,特别是手动测试方法.但只知道不同的测试概念只完 ...

  5. 史上最全Java面试题大汇总「百题附答案」

    前言 整理这些面试题源于在微信群和几个刚入职的小伙伴们的一次讨论,很多小伙伴谈了自己的面试经历和体会,很多人最初鄙视刷题党,觉得开发技能最重要,但在短暂的面试过程中很挫败.转而去看面试题,但是网上面试 ...

  6. Java面试题大汇总,2021年附答案解析

    最新常Java面试题大汇总(含答案解析)发现网上很多Java面试题都没有答案,所以花了很长时间搜集整理出来了这套Java面试题大全汇总,希望对大家有帮助哈 本套Java面试题大全,全的不能再全,哈哈~ ...

  7. 大型软件公司.net面试题!一定得看(附答案)

    1:a=10,b=15,在不用第三方变量的前提下,把a,b的值互换   2:已知数组int[] max={6,5,2,9,7,4,0};用快速排序算法按降序对其进行排列,并返回数组   3:请简述面向 ...

  8. BAT经典面试题精简版(基础知识附答案)

    文章目录 目录 J2SE基础 JVM 操作系统 TCP/IP 数据结构与算法 目录 J2SE基础 九种基本数据类型的大小,以及他们的封装类. 原始类型封装类 booleanBoolean charCh ...

  9. 面试 Redis 没底?这 40 道面试题让你不再慌(附答案)

    金三银四面试季,为了做好大家面试路上的助攻手,对于 Redis 这块心里还没底的同学,特整理 40 道Redis常见面试题,让你面试不慌,争取 Offer 拿到手软! 1.什么是 Redis? Red ...

最新文章

  1. 微信是个坑货4-网页授权
  2. 以后看下try,catch在C#下面的成本
  3. 团队开发软件特点介绍
  4. python watchdog 同时检测到多个事件_python中watchdog文件监控与检测上传功能
  5. win7上安装wince6.0
  6. php前端路由权限,SaaS-前端权限控制
  7. pythonweb项目面试题_python和web框架面试题目整理(1)
  8. ecshop首页显示折扣的方法,ecshop商品显示折扣的方法
  9. GO语言学习之路26
  10. 在CSDN开通博客专栏后如何发布文章及改进建议(图文)
  11. 爬取天天基金排行榜上的基金信息
  12. 5、ORB-SLAM闭环检测之通过求解出来的sim3寻找当前关键帧和闭环候选帧之间的更多匹配
  13. win10计算机屏幕暗怎么办,win10屏幕调到最亮还是很暗怎么办
  14. python怎么把ppt转成html,如何使用python把ppt转换成pdf
  15. java imageio 使用_java – 使用ImageIO发送图像流?
  16. 学python后的感想_学习python的感想
  17. 多元微积分(一)--导数与偏导数
  18. 全球及中国公共安全记录管理系统行业发展现状及前景趋势预测报告(2022-2027)
  19. 顺序表的建立和基本操作
  20. ftp服务器必须运行ftp服务器软件对吗,ftp是什么?FTP服务器搭建及选择

热门文章

  1. CSS深入理解学习笔记之vertical-align
  2. MySQL循环语句之while循环测试
  3. 诺基亚AirScale支持低频段和高频段5G服务 确保运营商投资收入
  4. Eclipse jetty和plugin 的结合使用
  5. shell timeout
  6. centos php 版本升级 至5.3 wordpress3.7
  7. MyBatis 数据持久层
  8. XenDesktop 5.5 – HDX RealTime TCP UDP Audio演示
  9. 分别用 数组和链表处理约瑟夫环问题
  10. java 删除二维数组中的null_避免在Java中检查Null语句