【Java IO之 认知提升】

1. 引入背景

    实际项目开发中使用到了Connection以及Channel,这些都是Java语言提供的
jar包工具,然而我们真的了解这个东西吗?
	实际上这个需要掌握socket的知识作为前置条件,才能了解地更透彻。
	那么就从如下几个问题来掌握吧!let 's go !

2. 问题

2.1 socket与channel ,使用socket创建的channel只是管理每一个输入输出流资源 ?

// 解析:
* Socket是一个抽象概念,表示两个网络节点之间的连接。它提供了建立连接、
	发送和接收数据的功能,socket可以看作是一个通信的端点,用于在网络上
	发送和接收数据。
* Channel是一个更低级别的概念,用于管理实际的输入输出流资源。Channel提
	供了对底层操作系统的文件、套接字、管道等进行读写的能力。它可以看作
	是对底层IO操作的抽象,提供了更直接和高效的数据传输方式。
* 在java中,Socket对象是对网络连接的抽象,通过Socket可以创建输入流和输
	出流来进行数据的读写。而Channel对象是对底层IO资源的抽象,可以通过
	Socket对象来获取对应的Channel对象,然后使用Channel来进行更底层的数
	据传输。
	在Java NIO中,提供了socketChannel和ServerSocketChannelChannel的实
	现类,用于进行非阻塞的网络通信。这些Channel可以通过Socket对象
	的getChannel()方法来实现。
* 总结:使用Socket创建的Channel并不是虚拟的,它是对底层的输入输出流资
	源的管理。通过Channel,可以进行更底层的数据传输和操作。

2.2 一个连接正在输入输出io流操作,那么获取到的另外一个channel可以进行io操作吗 ?

在同一个连接中,多个Channel之间是可以同时进行I/O操作的。

在Java NIO中,可以通过一个Socket对象获取多个Channel对象,这些Channel对
象可以并行地进行I/O操作。每个Channel对象都拥有自己的读取和写入缓冲区,
它们可以独立地进行数据的读取和写入。

多个Channel对象可以在同一个连接上进行并行的读取和写入操作,这样可以实
现更高效的数据传输。通过使用多个Channel对象,可以同时进行多个非阻塞的
I/O操作,提高了系统的并发性能。

需要注意的是,多个Channel对象之间的数据传输和操作需要进行同步控制,以
避免数据的不一致性或竞争条件。可以使用同步机制,如锁或同步器,来保证多
个Channel对象之间的操作的顺序和正确性。

总而言之,多个Channel对象可以在同一个连接上进行并行的I/O操作,但需要进
行适当的同步控制来确保数据的一致性和正确性。

2.3 负责channel的计算机部件是什么?

负责Channel的计算机部件是网络适配器(Network Adapter)或网卡(Network 
Interface CardNIC)。

网络适配器是计算机与网络之间的桥梁,它负责将计算机内部的数据转换为网
络可以传输的格式,并将接收到的网络数据转换为计算机可以理解的格式。网络
适配器通常包括一个物理接口,用于连接计算机与网络的物理介质(如以太网电
缆)。

在计算机中,每个网络适配器都有一个唯一的MAC地址(Media Access Control 
address),用于在网络中标识该适配器。当计算机通过网络进行通信时,可以
使用MAC地址来确定数据的发送和接收方。

网络适配器通过操作系统的驱动程序与计算机的操作系统进行通信。操作系统
提供了网络协议栈,包括TCP/IP协议等,用于处理网络通信。网络适配器将数
据从操作系统传输到网络,或者从网络接收数据并传输给操作系统。

因此,网络适配器是负责Channel的计算机部件,它实现了计算机与网络之间
的数据传输和通信功能。

2.4 网卡是一块芯片吗,它支持多线程吗?

是的,网卡(Network Interface Card,NIC)通常是一块物理芯片,也可以是一
个独立的硬件设备。它被插入计算机的主板上,用于实现计算机与网络之间的数
据传输。

网卡通常包含了一个网络适配器芯片,它负责处理网络数据的发送和接收。该芯
片包括了物理层和数据链路层的功能,可以将计算机内部的数据转换为网络可以
传输的格式,并将接收到的网络数据转换为计算机可以理解的格式。

网卡的设计可以支持多线程。现代的网卡通常具备多个队列(Queue),每个队
列对应一个线程或处理器核心。通过使用多个队列,网卡可以同时处理多个数
据流,提高网络传输的并发性能。

多线程的支持使得网卡可以同时处理多个数据包,提高了网络传输的效率。这对
于高速网络和高负载的服务器环境非常重要,可以更好地利用计算机的处理能力
和网络带宽。

总结起来,网卡通常是一块物理芯片或独立的硬件设备,它支持多线程,并负责
处理计算机与网络之间的数据传输。

2.5 那电脑连接的是WiFi,那么网卡是如何将光信号转换为电信号的?

当电脑连接WiFi时,通常是通过无线网卡(Wireless Network Adapter)来实现
的。无线网卡使用无线电波进行通信,而不是通过光信号。

无线网卡的工作原理是将电脑中的数据转换为无线电信号,并将其发送到无线路
由器或接入点。这个过程涉及到以下几个主要步骤:

1. 数据转换:电脑中的数据通常是以电信号的形式存在的。无线网卡首先将这
些电信号转换为无线电信号。这个转换过程通常由无线电调制解调器(wireless
radio modem)来完成。

3. 调制:在调制过程中,无线网卡将数字数据转换为模拟信号。这通常使用调
制技术(如正交频分复用(OFDM))来将数字数据转换为无线电信号。

4. 发送:无线网卡将调制后的无线电信号发送到无线路由器或接入点。这个过
程涉及到无线电天线(antenna)的使用,它将无线电信号转换为无线电波并
将其发送出去。

接收端的无线路由器或接入点会接收到这些无线电波,并将其转换为数字信号。
然后,接入点会将这些数字信号传输到互联网或局域网中。

需要注意的是,无线网卡并不是将光信号转换为电信号的设备。将光信号转换为
电信号的设备通常是用于光纤网络,如光纤网卡或光猫等。对于WiFi连接,无线
网卡使用无线电技术来进行数据传输。

2.6 无线电和光信号的区别?

无线电信号和光信号是两种不同的传输介质和传输方式。

1. 传输介质:无线电信号是通过无线电波在空气中传播的电磁波信号。它可以
在无线电频段进行传输,通常使用天线来发送和接收信号。光信号则是通过
光纤中的光脉冲进行传输的。光信号利用光的特性在光纤中传输,通常使用
光纤来发送和接收信号。

2. 传输速度:光信号的传输速度通常比无线电信号更快。由于光信号利用了
光的高频率和高速度特性,可以实现更高的数据传输速度。而无线电信号的
传输速度受到频段和信号质量等因素的影响,通常比光信号慢一些。

4. 传输距离:光信号在光纤中传输时,可以实现较长的传输距离,可以达到
几十公里甚至更远。而无线电信号在空气中传播时,传输距离通常较短,受到
环境、天线功率和障碍物等因素的影响。

5. 环境干扰:无线电信号容易受到环境干扰的影响。例如,建筑物、障碍物、
电磁干扰等都可能影响无线电信号的传输质量和距离。而光信号在光纤中传输
时,对这些环境因素的干扰相对较小。

综上所述,无线电信号和光信号是不同的传输介质和传输方式,它们在传输速
度、传输距离和环境干扰等方面存在差异。选择使用无线电信号还是光信号取
决于具体的应用需求和环境条件。

2.7 无阻塞io和阻塞io在操作系统层面是如何体现的?java提供的无阻塞io是咋么回事 ?

无阻塞 I/O(Non-blocking I/O)和阻塞 I/O(Blocking I/O)是两种不同的 
I/O操作模式,在操作系统层面和 Java 提供的 API 层面有不同的实现方式。

在操作系统层面,阻塞 I/O 是指当应用程序进行 I/O 操作时,如果数据没有
准备好或者无法立即发送,操作系统会将应用程序的线程阻塞(即暂停执行),
直到数据准备好或者发送完成。这意味着应用程序无法执行其他任务,直到 
I/O 操作完成。

而无阻塞 I/O 是指当应用程序进行 I/O 操作时,如果数据没有准备好或者无法
立即发送,操作系统不会阻塞应用程序的线程,而是立即返回一个结果,允许应
用程序继续执行其他任务。应用程序可以通过轮询(Polling)或者事件通知
(Event Notification)等方式来检查 I/O 操作的状态,以确定何时数据准备
好或者发送完成。

在 Java 中,提供了 NIO(New I/O) API,通过 java.nio 包来实现无阻塞 
I/O 操作。NIO 提供了 Channel 和 Selector 的概念,以及对应的非阻塞 I/O 
操作方法。通过使用 Selector,应用程序可以同时监视多个 Channel 的 I/O
事件,实现对多个 I/O 操作的非阻塞处理。

在无阻塞 I/O 模式下,应用程序可以在等待 I/O 操作完成的同时执行其他任务
,提高了系统的并发性能。但需要注意的是,无阻塞 I/O 需要应用程序主动地
检查 I/O 操作的状态,可能会导致 CPU 的占用率增加。因此,在选择使用阻
塞 I/O 还是无阻塞 I/O 时,需要根据具体的应用场景和需求来进行权衡和选
择。

2.8 本地服务器从另外一台云服务器拉取数据库数据,此过程比较耗时,如果程序采用非阻塞io,那么程序中的线程就不会阻塞,可以执行其他任务,而io数据的准备是使用的是内核线程吗?

在使用非阻塞IO的情况下,程序中的线程不会被阻塞,可以继续执行其他任务。非阻塞IO的特点是当没有数据
准备好时,立即返回,而不是阻塞等待数据的到来。

IO数据的准备过程通常是由操作系统内核完成的,而不是由用户程序的线程直接参与。当用户程序请求IO操作
时,内核会负责处理IO操作,包括建立连接、传输数据等。内核会使用自己的线程来处理这些IO操作,这些线
程通常被称为内核线程或者IO线程。

所以,IO数据的准备过程通常离不开内核线程,但与用户程序的线程是分开的。用户程序的线程可以继续执行
其他任务,而不会被IO操作的准备过程所阻塞。这样可以提高程序的并发性和响应性。

2.9 linux内核线程是多少个?

Linux内核线程的数量没有固定的限制,它可以根据系统的需求动态调整。内核线程是由操作系统内核创建和管
理的,用于执行一些系统级的任务,例如处理中断、调度进程、管理内存等。

在Linux系统中,内核线程通常以内核线程调度器(kernel thread scheduler)的形式存在。内核线程调度器负
责管理和调度内核线程的执行,根据系统的负载情况和优先级进行调度。

Linux系统中的内核线程数量可以通过/proc文件系统中的相关文件查看,例如/proc/thread-self/status或
者/proc/thread-self/task目录中的文件。但需要注意的是,这些文件只能显示当前进程所属的线程信息,而不
是整个系统的内核线程数量。

总之,Linux内核线程的数量是动态变化的,取决于系统的负载和需求。

2.10 非阻塞io 数据准备好了,是内核线程通知到应用程序吗?

是的,当非阻塞IO的数据准备好时,通常是通过内核线程通知应用程序。内核线程负责处理IO操作,包括建立
连接、传输数据等。当IO操作完成时,内核线程会将数据准备好的通知发送给应用程序。

在非阻塞IO的情况下,应用程序通过调用非阻塞IO的API发起IO操作,然后立即返回,不会阻塞等待数据的到
来。应用程序可以继续执行其他任务。当数据准备好后,内核线程会通知应用程序,通常是通过事件驱动的方
式,例如使用事件通知机制(如epoll、select、poll等)或者信号(如SIGIO信号)来通知应用程序。

应用程序在收到内核线程的通知后,可以通过相应的API调用来读取或处理已准备好的数据。这样可以实现异步
IO操作,在IO操作的同时继续执行其他任务,提高程序的并发性和响应性。

2.11 reactor io模型 中有mainReactor和subReactor,分析一下

在Reactor模型中,通常使用一个主Reactor(Main Reactor)和多个子Reactor(Sub Reactor)来处理IO事件。

主Reactor负责监听所有的IO事件,包括连接事件、读写事件等。它通常运行在单个线程上,使用非阻塞IO方式
进行事件监听。当有新的IO事件到达时,主Reactor会将该事件分发给一个或多个子Reactor。

子Reactor负责具体的IO事件处理和IO操作的执行。通常每个子Reactor运行在一个独立的线程上,使用非阻
塞IO方式进行事件处理和IO操作。子Reactor负责处理从主Reactor分发过来的事件,并根据事件类型执行相
应的操作,例如接受新连接、读取数据、发送数据等。

主Reactor和子Reactor的协作可以有效地提高系统的并发性能。主Reactor负责监听所有的IO事件,通过事件
分发机制将这些事件分发给多个子Reactor进行处理。子Reactor负责具体的IO操作,通过非阻塞IO方式来处
理IO事件,避免了传统的阻塞IO模型中的线程阻塞问题,提高了系统的并发处理能力。

需要注意的是,主Reactor和子Reactor的具体实现可能会有所不同,可以根据具体的框架或库来进行实现。
Reactor模型是一种通用的IO处理模型,被广泛应用于各种网络编程框架和库中,例如Netty、Java NIO等。

2.12 socket编程提供了哪些类与api方法?

在Socket编程中,常用的类和API方法包括:

1. Socket类:用于客户端与服务器之间建立TCP连接。可以通过该类的构造函数创建一个Socket对象,然后使用
	其提供的方法进行连接、发送和接收数据等操作。

2. ServerSocket类:用于创建服务器端的Socket对象,监听指定的端口,接受客户端的连接请求。可以通过该
的构造函数创建一个ServerSocket对象,然后使用其提供的方法进行监听、接受连接、发送和接收数据等操作。

4. InetAddress类:用于表示IP地址。可以通过该类的静态方法获取本地主机的IP地址,或者通过域名获取指定
	主机的IP地址。

5. InputStream和OutputStream类:用于在Socket中进行数据的输入和输出。可以通过Socket对象的
	getInputStream()和getOutputStream()方法获取对应的输入流和输出流,然后使用其提供的方法进行数据的
	读取和写入操作。

6. BufferedReader和PrintWriter类:用于更方便地进行文本数据的输入和输出。可以通过InputStreamReader将
 Socket的输入流包装成BufferedReader,然后使用BufferedReader的readLine()方法读取文本数据;同样,可以
 通过OutputStreamWriter将Socket的输出流包装成PrintWriter,然后使用PrintWriter的println()方法写入文本
  数据。

7. SocketException类:用于表示Socket相关的异常。在Socket编程中,可能会出现连接超时、连接断开等异常
	情况,可以通过捕获SocketException来处理这些异常。

8. SocketTimeoutException类:用于表示Socket超时异常。当Socket连接或操作超时时,可能会抛出
  SocketTimeoutException。

这些类和API方法是常用的Socket编程中的一部分,可以通过查阅相关文档和使用示例来更详细地了解和使用
它们。

2.13 操作系统层面,windows使用的是select,linux使用的是epoll?

是的。在操作系统层面,Windows和Linux使用了不同的机制来实现高效的I/O多路复用。

在Windows中,常用的是select函数。select函数是一个阻塞式的I/O多路复用函数,它可以同时监视多个文件
描述符的状态,并在其中任何一个文件描述符就绪时返回。通过select函数,可以实现非阻塞式的I/O操作,提
高程序的并发处理能力。

而在Linux中,常用的是epoll机制。epoll是一种事件驱动的I/O多路复用机制,它可以监视多个文件描述符的
状态,并在其中任何一个文件描述符就绪时通知应用程序。相比于select,epoll具有更高的性能和可扩展性,
尤其在大规模并发连接的场景下表现更好。

选择使用select还是epoll取决于操作系统和应用程序的需求。在Windows平台上,使用select函数是比较常见
的选择,而在Linux平台上,使用epoll机制能够更好地满足高并发的需求。

2.14 select 、poll、epoll 分别讲解一下?

当涉及到I/O多路复用时,select、poll和epoll是常用的机制。它们都用于监视多个文件描述符的状态,并在
其中任何一个文件描述符就绪时进行相应的处理。然而,它们在实现原理和性能方面有所不同。

1. select:
   - select是最古老的I/O多路复用机制,适用于各种操作系统。
   - 它使用fd_set数据结构来保存文件描述符,并通过select函数进行监视。
   - select函数是一个阻塞式的调用,它会一直等待,直到其中一个文件描述符就绪或超时。
   - 当文件描述符就绪时,select函数会返回,并通过遍历fd_set来确定哪个文件描述符可读或可写。
   - select的缺点是,每次调用时需要将所有待监视的文件描述符集合传递给内核,这会带来性能上的开销,
      尤其在大规模并发连接的情况下。

2. poll:
   - poll是select的改进版本,同样适用于各种操作系统。
   - 它使用pollfd数据结构来保存文件描述符,并通过poll函数进行监视。
   - poll函数是一个阻塞式的调用,类似于select,它会一直等待,直到其中一个文件描述符就绪或超时。
   - 与select不同的是,poll不需要将所有待监视的文件描述符集合传递给内核,而是通过一个pollfd数组来
      传递,减少了性能开销。
   - poll的缺点是,当待监视的文件描述符数量较大时,遍历整个pollfd数组来确定就绪的文件描述符会带来
     一定的开销。

3. epoll:
   - epoll是Linux特有的I/O多路复用机制,提供了更高性能和可扩展性。
   - 它使用三个系统调用:epoll_create、epoll_ctl和epoll_wait。
   - epoll_create用于创建一个epoll实例,epoll_ctl用于添加、修改或删除文件描述符的监视,epoll_wait
     用于等待文件描述符就绪。
   - epoll采用事件驱动的方式,将就绪的文件描述符放入一个就绪队列中,应用程序通过epoll_wait函数从
       队列中获取就绪的文件描述符。
   - epoll使用红黑树来存储待监视的文件描述符,以及就绪的文件描述符,因此在大规模并发连接的场景下
      表现更好。

总结:select、poll和epoll都是用于实现I/O多路复用的机制,但它们在实现原理和性能方面有所不同。select
是最古老的机制,适用于各种操作系统;poll是select的改进版,减少了性能开销;而epoll是Linux特有的机
制,提供了更高的性能和可扩展性,尤其在大规模并发连接的场景下表现更好。

2.15 select、和poll会阻塞,阻塞的是应用程序的线程还是操作系统的内核线程?

在select和poll机制中,阻塞是发生在应用程序的线程上,而不是操作系统的内核线程。

当应用程序调用select或poll函数时,这些函数会阻塞当前线程,直到其中一个文件描述符就绪或超时。
阻塞的意思是当前线程会暂停执行,不会继续往下执行后续的代码,直到满足了阻塞条件(文件描述符就绪
或超时)。

在这期间,操作系统的内核线程会负责监视文件描述符的状态,并在其中任何一个文件描述符就绪时通知应
用程序。一旦有文件描述符就绪,操作系统内核会唤醒被阻塞的应用程序线程,使其恢复执行。

因此,select和poll是阻塞调用,会暂停应用程序的线程,等待文件描述符就绪或超时。而操作系统的内核
线程会负责监视文件描述符的状态并通知应用程序。这种阻塞方式使得应用程序可以高效地处理多个文件
描述符,而不需要为每个文件描述符创建一个独立的线程。

2.16 那么select、poll属于阻塞io(IO复用)了呗?而epoll是事件驱动io,属于NIO?

是的,select和poll属于阻塞I/O模型,而epoll属于事件驱动I/O模型,也被称为NIO(Non-blocking I/O)。

在select和poll中,应用程序调用它们的函数会阻塞,直到其中一个文件描述符就绪或超时。这种阻塞方式会导致应用程序线程暂停执行,直到满足阻塞条件。

而epoll采用了事件驱动的方式,应用程序通过创建epoll实例,并将待监视的文件描述符添加到epoll实例中。当有文件描述符就绪时,操作系统会通知应用程序,应用程序可以通过epoll_wait函数从就绪队列中获取就绪的文件描述符。这种方式不需要阻塞应用程序线程,而是通过事件回调的方式进行处理。

因此,select和poll属于阻塞I/O模型,而epoll属于事件驱动I/O模型,也被称为NIO。NIO通过事件通知的方式,使得应用程序能够以非阻塞的方式进行I/O操作,并能够高效地处理多个并发连接。

2.17 NIO中的零拷贝是拷贝什么内容到哪里去?

在NIO(New Input/Output)中,零拷贝(Zero-copy)是指数据在内核空间和用户空间之间传递时,避免了数据
的多次复制。具体来说,零拷贝是指在数据传输过程中,数据从磁盘或网络读取到内核缓冲区后,直接从内核
缓冲区传递到用户空间的应用程序,而不需要经过中间的用户缓冲区。

在传统的I/O模型中,数据从磁盘或网络读取到内核缓冲区后,需要通过一次或多次的数据拷贝将数据从内核缓
冲区复制到用户缓冲区,然后再传递给应用程序。而在零拷贝模型中,数据从内核缓冲区直接传递到应用程序
,避免了数据的多次复制,提高了数据传输的效率和性能。

因此,NIO中的零拷贝是指数据从内核缓冲区直接传递到用户空间的应用程序,避免了数据的多次复制。这在处
理大量数据的情况下,可以显著提高数据传输的效率和性能。

3.总结

看到这里,其实你对io的认知已经提升了一个台阶了。无论是java,还是C++,亦或是python等编程语言,
都是对操作系统提供的api进行了封装和调用,只有熟悉别人给我们使用了什么工具,才能更熟练地明白
他们之间的关联与发展。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值