java NIO和Socket的区别
nio实现原理

nio实现原理NIO是Java SE 1.4版本引入的一种新的I/O模型,与传统的I/O模型相比,NIO可以实现更高效的I/O操作。
这里我们将围绕NIO 实现原理进行详细阐述。
NIO是基于Channel、Buffer、Selector三个核心组件实现的,下面将详细介绍这三个组件的实现原理。
一、ChannelChannel是一个具有双向I/O能力的数据传输管道,与传统的I/O模型中的Stream类似。
但是,Channel的I/O操作具备非阻塞特性,可以实现更高效的I/O操作。
Channel包括了ServerSocketChannel、SocketChannel等,可以通过Channel的open 方法创建一个具体的Channel实例。
二、BufferBuffer是一个用于数据存储的缓冲区,可以将数据写入缓冲区或者从缓冲区读取数据,Buffer实现了对数据的高效存储与读写操作。
Buffer包含了ByteBuffer、CharBuffer等实现,可以通过Buffer的allocate方法创建具体的Buffer实例。
三、SelectorSelector是一个具有监控多个Channel的兴趣事件能力的对象,常用于服务器端实现多个Channel的管理。
Selector实现了高效的事件通知机制,可以将兴趣事件通知给应用程序进行响应处理。
Selector通过Selector.open方法创建具体的Selector实例。
NIO通过上述三个核心组件实现了高效的I/O操作,具备更高的并发性和可扩展性。
NIO的实现过程可以简单概括为:1. 创建ServerSocketChannel,并将其注册到Selector中;2. Selector等待客户端请求,并通知ServerSocketChannel;3. ServerSocketChannel接受请求,创建SocketChannel,并将其注册到Selector中;4. Selector等待SocketChannel感兴趣的事件并通知应用程序进行响应处理;5. 应用程序通过SocketChannel进行数据读取或数据写入操作。
Java NIO:文件读写的现代演绎

Java NIO:文件读写的现代演绎《Java NIO:文件读写的现代演绎》在Java的世界中,自NIO(New Input/Output)问世以来,文件的读写操作便开启了新的篇章。
NIO不仅提升了性能,还为开发者带来了更为丰富和灵活的编程模式。
本文将深入探讨Java NIO在文件读写方面的应用,揭示其背后的设计哲学和实际效能。
一、NIO的诞生:传统IO的挑战与革新在NIO出现之前,Java的IO操作主要依赖于流(Streams)和字节(Bytes)的读写,这种方式虽然直观,但在处理大文件或需要高并发的场景时,其性能瓶颈逐渐显现。
NIO的引入,通过通道(Channels)和缓冲区(Buffers)的机制,为文件读写带来了革命性的改变。
二、通道与缓冲区:NIO的双剑合璧NIO的核心在于通道和缓冲区的配合使用。
通道负责数据的读写,而缓冲区则作为数据的中转站。
这种设计使得数据的读写可以更加高效,因为它减少了实际的IO操作次数,并通过缓冲区的预读和批量写入,提高了数据处理的速度。
三、缓冲区的精细控制:rewind、flip与clear在NIO的编程实践中,对缓冲区的控制至关重要。
rewind()、flip()和clear()是三个关键的操作,它们分别用于重置缓冲区的位置指针、切换缓冲区的读写模式以及清空缓冲区。
这些操作的正确使用,直接关系到数据读写的正确性和效率。
四、文件读写的NIO实践:从理论到实战在实际应用中,NIO的文件读写操作涉及对FileChannel 的运用。
通过FileInputStream或FileOutputStream获取FileChannel,然后配合ByteBuffer进行数据的读写。
这一过程不仅要求开发者对NIO的API有深入的理解,还需要对文件的读写逻辑进行精心设计。
五、性能考量:NIO与旧IO的较量虽然NIO在理论上提供了更高的性能,但在实际应用中,其优势并非在所有场景下都显而易见。
同步异步,阻塞非阻塞,IO模型,边缘触发(EdgeTrigger)和条件触发(LevelT。。。

同步异步,阻塞⾮阻塞,IO模型,边缘触发(EdgeTrigger)和条件触发(LevelT。
1.同步和异步同步和异步其实是指CPU时间⽚的利⽤,主要看请求发起⽅对消息结果的获取是主动发起的,还是被动通知的,如下图所⽰。
如果是请求⽅主动发起的,⼀直在等待应答结果(同步阻塞),或者可以先去处理其他事情,但要不断轮询查看发起的请求是否有应答结果(同步⾮阻塞),因为不管如何都要发起⽅主动获取消息结果,所以形式上还是同步操作。
如果是由服务⽅通知的,也就是请求⽅发出请求后,要么⼀直等待通知(异步阻塞),要么先去⼲⾃⼰的事(异步⾮阻塞)。
当事情处理完成后,服务⽅会主动通知请求⽅,它的请求已经完成,这就是异步。
异步通知的⽅式⼀般通过状态改变、消息通知或者回调函数来完成,⼤多数时候采⽤的都是回调函数。
2.阻塞和⾮阻塞阻塞和⾮阻塞在计算机的世界⾥,通常指针对I/O的操作,如⽹络I/0和磁盘I/0等。
那么什么是阻塞和⾮阻塞呢?简单地说,就是我们调⽤了⼀个函数后,在等待这个函数返回结果之前,当前的线程是处于挂起状态还是运⾏状态。
如果是挂起状态,就意味着当前线程什么都不能⼲,就等着获取结果,这就是同步阻塞;如果仍然是运⾏状态,就意味着当前线程是可以继续处理其他任务的,但要时不时地看⼀下是否有结果了,这就是同步⾮阻塞。
具体如下图所⽰。
3.实际⽣活场景同步、异步、阻塞和⾮阻塞可以组合成上⾯提到过的四种结果。
举个例⼦,⽐如我们去照相馆拍照,拍完照⽚之后,商家说需要30min左右才能洗出来照⽚。
(1)这个时候,如果我们⼀直在店⾥⾯什么都不⼲,⼀直等待直到洗完照⽚,这个过程就叫同步阻塞。
(2)当然,⼤部分⼈很少这么⼲,更多的是⼤家拿起⼿机开始看电视,看⼀会⼉就会问⽼板洗完没,⽼板说没洗完,然后接着看,再过⼀会⼉接着问,直到照⽚洗完,这个过程就叫同步⾮阻塞。
(3)由于店⾥⽣意太好了,越来越多的⼈过来拍,店⾥⾯快没地⽅坐了,⽼板说你把⼿机号留下,我⼀会⼉洗好了就打电话告诉你过来取,然后你去外⾯找了⼀个长凳开始躺着睡觉等待⽼板打电话,什么都不⼲,这个过程就叫异步阻塞(实际不应⽤)。
【Java】Javasocket通信使用read,readline函数的阻塞问题

【Java】Javasocket通信使⽤read,readline函数的阻塞问题Socket通信是Java⽹络编程中⽐较基础的部分,其原理其实就是源ip,源端⼝和⽬的ip,⽬的端⼝组成的套接字通信。
其底层还设及到了TCP协议的通信。
Java中的Socket通信可以通过客户端的Socket与服务端的ServerSocket通信,同时利⽤IO流传递数据,也就是说Socket通信是⾯向流的使⽤的是BIO,并不同于后来的NIO通信⾯向缓冲。
Socket通信中使⽤的IO流的read,readline等函数都是阻塞的,这就导致了在通信过程中,双⽅不能确定什么时侯是流的结束,针对这种可以通过约定结束符的⽅式进⾏结束,也可以约定⼀次传输的字节流的长度。
下⾯通过代码进⾏说明客户端建⽴客户端线程,在run⽅法中不断对服务端进⾏发送消息,模拟多个客户端的通信,通过写⼊换⾏符,表明这次通信的结束。
1class Client implements Runnable {23private byte[] targetIp;4private int port;56 Client(byte[] ip, int port) {7this.targetIp = ip;8this.port = port;9 }1011 @Override12public void run() {13try {14 InetAddress inetAddress = InetAddress.getByAddress(targetIp);15 Socket socket = new Socket(inetAddress, port);16 System.out.println("client");17 BufferedReader socketInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));18 BufferedWriter socketOutput = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));1920int i = 0;21 String NAME = "Client";22while (true) {23 socketOutput.write("This msg from " + NAME + " msg id is " + i);24 socketOutput.write("\n");//约定结束符表⽰流的结束25 i++;26 socketOutput.flush();27 System.out.println("here");28 String str = null;29if (!(str = socketInput.readLine()).equals("\n")) {30 System.out.println(str);31 }3233 }3435/*socket.shutdownInput();36 socket.shutdownOutput();*/37 } catch (IOException e) {38 e.printStackTrace();39 }4041 }42 }服务端服务端通过accept接受客户端的连接,这个操作是阻塞的,直到有客户端的连接才能进⾏下⼀步。
nio 原理

nio 原理
nio(非阻塞I/O)是一种用于处理I/O操作的优化技术。
它旨在提高系统的吞吐量和响应能力,避免线程阻塞导致的资源浪费。
传统的I/O模型中,在进行I/O操作时,线程会被阻塞,直到I/O操作完成。
这种模型在面对大量的并发连接时效率较低,因为每个连接需占用一个线程,而线程是相对较宝贵的资源。
nio通过引入了以下关键组件来优化I/O操作:
1. 通道(Channel):用于数据的传输,允许同时进行输入和输出操作,例如读取和写入文件。
2. 缓冲区(Buffer):存储数据的区域,用于在通道和应用程序之间传输数据。
3. 选择器(Selector):负责管理多个通道,实现单个线程处理多个I/O操作的能力。
nio通过非阻塞的方式进行I/O操作,即当一个通道上的数据还未准备好时,线程不会被阻塞,而是可以处理其他的操作。
这使得一个线程可以同时处理多个连接的I/O操作,提高了系统的吞吐量。
使用nio的基本流程如下:
1. 创建一个选择器(Selector)。
2. 创建通道(Channel),并将其注册到选择器上。
3. 在一个循环中,调用选择器的select()方法等待通道上的I/O 事件。
4. 当某个通道上有I/O事件发生时,通过选择器获取对应的通道和缓冲区,进行读取或写入操作。
5. 根据具体业务需求,处理读取到的数据或写入的数据。
6. 重复步骤3-5,直到所有需要处理的事件都处理完毕。
总之,nio通过非阻塞的方式,并借助于选择器、通道和缓冲区等组件,实现了高效的I/O操作处理。
它在处理大量并发连接时表现出色,成为了高性能网络编程的重要基础。
nio底层实现原理

nio底层实现原理一、引言nio(New I/O)是Java 1.4引入的一种新的I/O机制,它提供了一种非阻塞的、基于通道的I/O操作方式,相对于传统的I/O操作方式,在处理大量并发连接时具有更高的效率和可扩展性。
本文将介绍nio底层实现原理,帮助读者更好地理解和应用nio技术。
二、nio概述nio是Java对传统的阻塞式IO(BIO)的改进,它引入了新的抽象概念:通道(Channel)和缓冲区(Buffer)。
在传统的BIO中,每个连接都需要一个独立的线程来处理读写操作,当并发连接数较高时,线程资源消耗过大。
而nio则通过使用少量的线程来处理大量的并发连接,提高了系统的可扩展性。
三、nio底层实现原理1. 通道(Channel)通道是nio的核心概念之一,它代表与实体(如文件、网络套接字)之间的连接。
通道可以用于读取和写入数据,而且通道可以是双向的,即可以同时进行读写操作。
通道的实现类包括FileChannel、SocketChannel、ServerSocketChannel和DatagramChannel等。
2. 缓冲区(Buffer)缓冲区是nio的另一个核心概念,它是一个连续的、有限容量的数据存储区域。
在nio中,数据的读写都是通过缓冲区来实现的。
缓冲区提供了一系列的方法来操作数据,包括put、get、flip、clear 等。
nio中的缓冲区实现类包括ByteBuffer、CharBuffer、IntBuffer等。
3. 选择器(Selector)选择器是nio的另一个重要组件,它用于监听多个通道的事件,当某个通道发生了感兴趣的事件时,选择器就会通知应用程序进行处理。
通过使用选择器,应用程序可以使用较少的线程来处理大量的并发连接。
选择器的实现类为Selector。
4. 非阻塞式IO操作在传统的BIO中,当一个线程在执行IO操作时,如果没有数据可读,则会被阻塞,直到有数据可读。
而在nio中,可以通过设置通道为非阻塞模式来实现非阻塞式IO操作。
nio的原理

nio的原理NIO的原理。
NIO,即New I/O,是Java 1.4引入的一种新的I/O模型,它提供了更高效的I/O操作方式,适用于处理大量并发连接的场景。
NIO的核心在于通道(Channel)和缓冲区(Buffer),它们可以提供非阻塞式的I/O操作,使得一个线程可以处理多个连接,大大提高了系统的并发处理能力。
在传统的I/O模型中,每个连接都需要一个独立的线程来处理,当连接数量增多时,线程的开销也会随之增加,导致系统资源的浪费。
而NIO采用了事件驱动的方式,通过Selector来监听多个通道上的事件,当某个通道上有数据可读或可写时,Selector会通知相应的线程进行处理,这样就避免了为每个连接都创建一个线程的开销。
NIO的原理可以简单概括为以下几点:1. 通道(Channel),通道是NIO中的核心概念,它类似于传统I/O中的流(Stream),但更加灵活和高效。
通道可以双向传输数据,而且可以非阻塞地进行读写操作。
通道可以连接到文件、套接字、管道等不同的数据源,使得数据的传输更加灵活多样。
2. 缓冲区(Buffer),缓冲区是NIO中用来存储数据的对象,它可以在内存中分配一块连续的空间来存储数据。
与传统I/O中的流不同,缓冲区可以随时读写数据,而且可以直接操作缓冲区中的数据,而不需要像流一样需要进行读取或写入操作。
3. 选择器(Selector),选择器是NIO中的另一个重要概念,它用来监听多个通道上的事件,比如可读、可写等。
当某个通道上有事件发生时,选择器会通知相应的线程进行处理,这样就实现了多路复用,使得一个线程可以处理多个通道上的事件。
通过以上几点,可以看出NIO的原理是基于非阻塞式的I/O操作,利用通道、缓冲区和选择器来实现高效的并发处理。
相比传统的I/O模型,NIO可以更好地适应大量并发连接的场景,提高系统的处理能力和性能。
总的来说,NIO的原理虽然比较复杂,但是通过合理的使用通道、缓冲区和选择器,可以实现高效的I/O操作,提高系统的并发处理能力,是现代网络编程中不可或缺的重要技术。
java nio socketchannel 用例-概述说明以及解释

java nio socketchannel 用例-概述说明以及解释1.引言1.1 概述在计算机网络通信中,传统的IO操作(即阻塞IO)往往会导致单线程无法高效处理多个网络连接。
为了解决这个问题,Java引入了NIO(New IO)机制,其中SocketChannel是NIO中最重要的一个组件之一。
Java NIO的背后思想是通过事件驱动模型实现非阻塞式IO操作。
相比传统的阻塞IO,NIO利用Selector选择器、Channel通道和Buffer 缓冲区的概念来实现高效的网络通信。
SocketChannel是NIO中提供网络连接的通道之一,它可以与一个TCP连接进行交互。
与传统的Socket不同,SocketChannel是非阻塞的,这意味着它可以在没有数据可读写时立即返回而不会阻塞线程,从而允许单线程同时处理多个连接。
SocketChannel通过Buffer进行数据读写,可以使用多种类型的Buffer来满足不同的需求,例如ByteBuffer、CharBuffer、IntBuffer等。
通过Buffer,SocketChannel可以实现高效的数据传输。
在本文中,我们将深入探讨SocketChannel的使用场景、优势和不足,以及它与NIO的关系。
通过了解SocketChannel的用例,读者将能够更好地理解和应用Java NIO的特性,并在网络编程中实现高效的数据传输和处理。
1.2文章结构1.2 文章结构本文将围绕Java NIO的SocketChannel展开详细讨论。
下面是本文的结构说明:1. 引言1.1 概述1.2 文章结构(即本节)1.3 目的2. 正文2.1 SocketChannel简介- SocketChannel的定义和作用- SocketChannel与传统IO的对比2.2 NIO简介- NIO的概念和特点- NIO中的关键组件和概念解析(Buffer、Channel、Selector等)- NIO与传统IO的对比3. 结论3.1 应用场景- SocketChannel的典型应用场景3.2 优势和不足- SocketChannel的优势- SocketChannel的不足与局限性通过以上结构,本文将全面介绍SocketChannel的基本概念和用法,并与传统IO进行对比,以便读者能够更好地理解NIO编程模型和SocketChannel的应用场景。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
本文并非Java.io或Java.nio的使用手册,也不是如何使用Java.io与Java.nio的技术文档。
这里只是尝试比较这两个包,用最简单的方式突出它们的区别和各自的特性。
Java.nio提出了新的流(stream)通讯概念并且加入了新的缓冲、文件流以及socket(套接字)特性。
java.io 概览这个包通过数据流和序列化机制来实现系统输入和输出。
并且支持多种类型的数据流,包括简单的字节、原生数据类型、地区字符以及对象。
流是一个数据的序列:一个程序使用输入流从一个源头读取数据;这些程序都使用字节流来执行字节的输入和输出。
所有涉及字节流的类都是继承自InputStream和OutputStream。
关于InputStream 和OutputStream执行InputStream和OutputStream的操作一般都意味着不断循环的将字节逐一从输入流读出或写入到输出流。
你可以使用缓冲I/O流来降低I/O成本(凡是I/O请求都经常触发磁盘访问、网络动作或其他一些成本昂贵的操作)。
缓冲输入流则是从缓冲的内存区域读取数据,只有缓冲读完才会调用native input API(不同操作系统提供的本地输入流API——译者注)。
同样的,缓冲输出流也将数据写入缓冲,只有缓冲写满才会调用native output API。
这些带缓冲的API很好的封装了未缓冲的流操作:BufferedInputStream 和BufferedOutputStream.File I/O上面一节主要是针对数据流,它提供一种数据读取和写入的简单模型。
真实的数据流其实是涉及种类繁多的数据源和目的地,包括磁盘文件。
但是,数据流并不支持所有磁盘文件操作。
下面的链接介绍了非数据流的文件I/O:∙File类可以编写平台无关的检查和处理文件、目录的代码。
∙Random access files支持非序列化的磁盘文件数据访问。
socket两个在网络上运行的程序之间会建立双向通讯的链接,socket就是其中一个端点。
Socket 相关的类代表着客户端程序和服务端程序之间的连接。
包提供了两个类:Socket 和ServerSocket。
它们分别实现了连接的客户端和服务端。
客户端知道服务端运行机器的域名,以及服务器监听的端口,它尝试连接到服务器,如果一切正常,服务器接受并建立连接。
当接受连接时,服务器在监听端口上绑定一个新的socket,并且通知远程端点设置客户端的地址和端口。
之所以要建立一个新的socket是为了处理已连接客户端请求的同时还能继续监听原始socket上的连接请求。
服务器使用阻塞模式等待客户端连接:serverSocket.accept()是一个阻塞指令,当服务器等待接受连接时主线程不能做任何其他操作。
由于这个原因,服务器想要达到多任务处理就只能通过实现一个多线程服务器:每当新建一个socket时就必须为它创建一个新线程。
NIO APII/O性能经常是一个现代应用的痛处。
操作系统持续优化改进I/O性能,JVM也提供了一套运行环境帮助Java程序员规避了绝大多数操作系统I/O之间的差异。
这些都让I/O相关编码更加高效和简单,但是却隐藏了操作系统的功能特性。
想要增强I/O性能,其实你可以通过一些特殊的编码直接访问操作系统的底层功能,但是这并不是最佳解决方案——你的代码将必须依赖某个操作系统。
Java.nio包应运而生来解决这个难题,它提供了高性能的I/O特性,并支持当今大多数常用的商用操作系统。
JDK1.4的NIO包介绍了一系列新的I/O操作的抽象概念。
java.nio 概览Java.nio这个新增的包实现了Java平台新的I/O API。
NIO API 包含如下特性:∙原生类型数据缓冲∙字符集的编码器和解码器∙基于Perl风格正则表达式的模式匹配∙通道(Channel),一种新的原生I/O抽象概念∙支持锁和内存映射的文件接口∙通过多路复用、非阻塞的I/O能力实现可伸缩的服务器架构在SUN(现Oracle)的站点上可以找到java.nio的详细技术文档。
这里我将解释一些nio 的概念,并且和老的java.io库做下比较。
建议不要把java.nio当作java.io的替代品,即使它是java.io的“扩展”。
Nio的诞生导致了整个I/O类和接口的重新修订(详情请看)。
NIO中一个最重要的概念是在非阻塞模式下运行,与传统Java I/O类库完全不同。
什么是非阻塞模式?Non blocking mode 非阻塞模式一个I/O流的字节必须序列化的访问。
各种设备,打印机端口、网络连接等都是常见的例子。
数据流通常比阻塞式设备慢,而且经常断断续续。
大多数操作系统允许将数据流设置为非阻塞模式,允许进程检查是否流上是否有可用数据,即使没有也不会导致进程阻塞。
这种机制能让进程在输入流空闲等待时执行其他逻辑,但是数据到达时又能及时处理。
操作系统能够观察一堆的数据流并且指示其中哪些处于可用状态。
通过观察这些可用状态,一个进程可以采用常用的编码和单个线程就能同时处理多个活动的数据流。
这在网络服务器处理大量网络连接时被广泛使用。
Buffers 缓冲从简单的入手,首先的改进是一系列java.io包中新建的缓冲类。
这些缓冲提供了一个可以在内存容器中存储一堆原生类型数据的机制。
一个缓冲对象是一个固定容量的容器,容器中的数据可以被读写。
所有的缓冲都是可读的,但并非都是可写的。
每个缓冲类都实现了isReadOnly()方法来表示缓冲内容是否允许被修改。
Channels缓冲需要配合Channel来使用。
Channel是I/O传输的入口,缓冲则是数据传输的源头或目的地。
在写入时,你想发送的数据首先被放入缓冲,接着被传递至一个Channel;在读取时,Channel负责接收数据,然后寄存至你提供的缓冲中。
(比如在网络传输时的过程:用户数据——>发送端缓冲——>发送端Channel——>网络传输——>接收端Channel ——>接收端缓冲——>用户数据,译者注)Channel就像一个管道一样,将数据在管道两端的字节缓冲之间进行高效率的传输。
它就像是一个网关,通过它可以用最小的成本来访问操作系统本地的I/O服务,而缓冲则是在两端内部的端点,Channel使用它来发送和接收数据。
Channel能在非阻塞模式下运行。
一个非阻塞模式下的Channel不会让调用线程睡眠。
请求的操作要么立刻完成、要么返回一个结果告知什么都没做。
只有面向数据流的Channel,比如socket,能够在非阻塞模式下运行。
在java.nio中的Channel包括FileChannel、ServerSocketChannel以及SocketChannel;这些都是为文件和socket管理所提供的特定的Channel。
FileChannelFileChannel是可读可写的Channel,它必须阻塞,不能用在非阻塞模式中。
面向数据流I/O 的非阻塞风格并不适合面向文件的操作,因为文件I/O有本质上的区别。
FileChannel对象不能被直接创建。
一个FileChannel实例只能通过在打开的文件对象(RandomAccessFile、FileInputStream、或FileOutputStream)上调用getChannel()得到。
GetChannel()方法返回一个连接到相同文件的FileChannel对象,与文件对象拥有相同的访问权限。
FileChannel对象是线程安全的。
多线程能够并发的调用同一个实例上的方法而不会导致任何问题,但是并非所有操作是支持多线程的。
影响Channel位置或者文件大小的操作必须是单线程的。
使用FileChannel,可以让拷贝等操作变成Channel到Channel的传输(transferTo()和transferFrom()方法),而且读写操作更易于使用缓冲。
SocketChannelSocketChannel与FileChannel不同:新的Socket Channel能在非阻塞模式下运行并且是可选择的。
不再需要为每个socket连接指派线程了。
使用新的NIO类,一个或多个线程能管理成百上千个活动的socket连接,只用到很小甚至0的性能损失。
使用Selector对象可以选择可用的Socket Channel。
有3个Socket Channel类型:SocketChannel, ServerSocketChannel, 以及DatagramChannel; SocketChannel和DatagramChannel是可读可写的,ServerSocketChannel 监听到来的连接,并且创建新的SocketChannel 对象。
所有这些SocketChannel初始化时会创建一个同等的socket对象( sockets)。
这个同等的socket能从Channel对象上调用socket()方法获取。
每个Socket Channel (in java.nio.channels)对象拥有一个相关的.socket对象,反之并非所有的socket对象拥有相关的Channel对象。
如果你使用传统方式创建一个socket对象,直接初始化它,它将不会拥有一个相关的Channel对象,它的getChannel()方法会返回null。
Socket Channel能在非阻塞模式下运行。
传统Java Socket阻塞的本性曾经是影响Java 应用可伸缩性的罪魁祸首之一。
而基于非阻塞I/O则构建了很多复杂巧妙的、高性能的应用。
设置或重置Channel的阻塞模式很简单,只要调用configureBlocking()即可。
非阻塞socket常在服务器端使用因为它能让同时管理多个socket变得简单。
Selector 选择器选择器(Selector)提供了挑选可用状态Channel的能力,从而实现多路复用的I/O。
我下面的例子将很好的解释选择器的优势:设想你在一个火车站(non-selector,非选择器场景),有3个平台(channels), 每个平台都有火车到达(buffer,缓冲)。
每个平台上都有个管理员管理着到达的列车(worker thread,工作线程)。
这是非选择器的场景。
现在设想下选择器场景。
有3个平台(channels),每个平台会有火车到达(缓冲),每个平台都有个指示器(比如一个响铃)指示着“火车到达”(selection key)。
在这个场景下只有一个管理员就可以管理所有的3个平台。
他只需查看指示器(selector.select())来判断是否有火车到达然后去处理一下到达的列车。
理解selector场景的优势很简单:一个单线程就可以实现多重任务处理的应用。