Java NIO - IO多路复用

目录

IO模型

IO实现

同步阻塞IO

核心流程

交互流程

同步阻塞IO模型

同步非阻塞IO

核心流程

交互流程

同步非阻塞IO模型

总结

优点

缺点

SELECT核心流程

交互流程

IO多路复用模型

总结

优点

缺点

POLL

优点

缺点

EPOLL核心流程

交互流程

总结

优点

缺点

LT VS ET

总结


IO模型

在Java中,常见的IO模型有4种,

  • 同步阻塞IO(Blocking IO)
  • 同步非阻塞IO(Non-blocking IO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为NONBLOCK。注意这里所说的NIO并非Java的NIO(New IO)库。
  • IO多路复用(IO Multiplexing):也称为异步阻塞IO,Java中的Selector和Linux中的epoll都是这种模型。这里复用的是指复用一个或几个线程,用一个或一组线程处理多个IO操作,减少系统开销小,不必创建和维护过多的进程/线程;
  • 异步IO(Asynchronous IO):即经典的Proactor设计模式,也称为异步非阻塞IO。

IO实现

目前流程的多路复用IO实现主要包括四种: selectpollepollkqueue。下表是他们的一些重要特性的比较:

IO模型 相对性能 关键思路 操作系统 JAVA支持情况
select 较高 Reactor windows/Linux 支持,Reactor模式(反应器设计模式)。Linux操作系统的 kernels 2.4内核版本之前,默认使用select;而目前windows下对同步IO的支持,都是select模型
poll 较高 Reactor Linux Linux下的JAVA NIO框架,Linux kernels 2.6内核版本之前使用poll进行支持。也是使用的Reactor模式
epoll Reactor/Proactor Linux Linux kernels 2.6内核版本及以后使用epoll进行支持;Linux kernels 2.6内核版本之前使用poll进行支持;另外一定注意,由于Linux下没有Windows下的IOCP技术提供真正的 异步IO 支持,所以Linux下使用epoll模拟异步IO
kqueue Proactor Linux 目前JAVA的版本不支持

多路复用IO技术最适用的是“高并发”场景,所谓高并发是指1毫秒内至少同时有上千个连接请求准备好。其他情况下多路复用IO技术发挥不出来它的优势。另一方面,使用JAVA NIO进行功能实现,相对于传统的Socket套接字实现要复杂一些,所以实际应用中,需要根据自己的业务需求进行技术选择。

同步阻塞IO

核心流程

当应用程序发起 read 系统调用时,在内核数据没有准备好之前,应用程序会一直处于阻塞等待状态,直到内核把数据准备好了返回给应用程序

交互流程

1)服务端进行初始化:新建 socket、绑定地址、转为服务端 socket

2)服务端调用 accept,进入阻塞状态,等待客户端连接

3)客户端新建 socket,向服务端发起连接

4)服务端和客户端通过 TCP 三次握手建立连接

5)服务端继续执行 read 函数,进入阻塞状态,等待客户端发送数据

6)客户端向服务端发送数据

7)服务端读取数据,执行逻辑处理

同步阻塞IO模型

1)应用进程发起 read 系统调用

2)应用进程阻塞等待数据就绪

3)数据通过网络传输到达网卡,然后再到内核socket缓冲区,当数据被拷贝到内核 socket 缓冲区时,此时处于就绪状态

4)将数据从内核拷贝到应用程序缓冲区,返回成功

多线程版本:文中使用的例子是单线程,如果是多线程则在每个 socket 建立连接后新建线程去负责处理该 socket 后续的流程,这样就不会由于单个 socket 阻塞住而影响到其他 socket。

总结

单线程:某个 socket 阻塞,会影响到其他 socket 处理。

多线程:当客户端较多时,会造成资源浪费,全部 socket 中可能每个时刻只有几个就绪。同时,线程的调度、上下文切换乃至它们占用的内存&

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
### 回答1: Java的虚拟线程是指在Java程序中使用的线程,它是运行在操作系统的内核线程之上的一层抽象。虚拟线程主要用于线程调度和线程池实现,可以有效地管理系统资源并避免线程频繁创建和销毁带来的开销。 IO复用是指程序可以同时监听多个网络套接字的输入输出事件,当某个事件发生时能够及时地做出响应。它可以使用多个线程或者单个线程实现,可以大大提升程序的吞吐量和效率。 ### 回答2: Java的虚拟线程是指在Java中使用的一种线程模型,称为"弹性线程池"。传统的线程模型中,每个线程都需要占用一个操作系统的线程资源,当需要创建大量的线程时,会耗费大量的内存和线程切换开销。而虚拟线程可以通过使用少量的线程,动态地处理多个任务。虚拟线程采用了协程的概念,可以在一个线程中动态开启和暂停多个任务,从而提高了并发性能。 而IO复用是一种IO模型,可以在一个线程中同时监听多个IO事件。在传统的阻塞IO模型中,每个客户端连接都需要一个线程来处理,当连接数增加时,线程数量也会相应增加,导致系统资源浪费。而IO复用通过一个线程管理多个IO事件,并且只在有事件发生时才会进行处理,大大提高了系统的并发能力。 Java中的IO复用主要通过选择器(Selector)来实现,它可以监控多个通道的IO事件,并在事件发生时通知线程进行处理。在利用选择器进行IO复用时,可以使用非阻塞IO来处理连接,即一个线程可以同时处理多个连接,提高了系统的吞吐量和响应速度。 虚拟线程和IO复用Java中都是为了提高系统的并发性能和资源利用率。虚拟线程通过动态的任务调度和协程的概念,实现了在少量线程上同时执行多个任务的能力。IO复用则通过一个线程同时监听多个IO事件的方式,减少了线程切换和系统资源的开销。这两个技术的结合可以进一步提高Java程序的并发处理能力,并优化系统的性能表现。 ### 回答3: Java的虚拟线程是指Java虚拟机(JVM)在操作系统的线程之上提供的一种更高级别的并发性抽象。它将操作系统线程映射到Java线程,并通过使用线程池技术来管理线程的生命周期。虚拟线程可以更有效地使用操作系统线程资源,减少线程的创建和销毁开销,并提供更高的并发性能。它还提供了一些高级并发特性,例如线程池的线程重用、线程的优先级管理和线程间的协作等。通过使用虚拟线程,开发人员可以更方便地编写高并发的Java程序,同时充分利用操作系统的硬件并发性。 IO复用是一种利用操作系统提供的非阻塞IO机制来同时监听多个IO通道的技术。它通过将多个IO通道注册到一个选择器对象(Selector)上,并在有IO事件发生时,使用单个线程来处理所有已注册的IO通道。这种方式可以大大减少线程的创建和销毁开销。在Java中,通过使用NIO(New IO)的特性,可以方便地实现IO复用Java中的Selector类提供了对多复用的支持,可以同时监听多个通道的IO事件,并通过“就绪集合”来获取已发生的事件。开发人员可以使用Selector来监测多个通道的IO状态,并根据不同的事件类型来执行相应的处理逻辑。 总之,Java的虚拟线程和IO复用都是为了提高Java程序的并发性能和资源利用效率。虚拟线程将操作系统线程映射到Java线程,并提供更高级别的并发性抽象,可以更高效地管理线程资源。而IO复用则利用非阻塞IO和选择器来同时监听多个IO通道的IO事件,减少线程开销,提高IO处理性能。这些技术在Java程序中的应用可以帮助开发人员更好地处理高并发和大量IO操作的场景。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LiarBoy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值