简述
Java 的 IO 方式大致可分为 3 类:BIO、NIO、NIO 2(AIO)
这 3 类 IO 方式在 同步/异步 和 阻塞/非阻塞 方面有明显区别。
同步 vs 异步
同步:后续任务必须等当前调用返回后再执行。
异步:后续任务不需要等待当前调用返回,依靠事件、回调等机制实现任务间次关系。
阻塞 vs 非阻塞
阻塞:执行阻塞操作时,当前线程会处于阻塞状态,无法执行其它任务,只有条件就绪后才能继续。
非阻塞:不管操作是否结束,当前线程直接返回,由后台其它线程继续处理。
BIO
BIO 指传统的 java.io 包,也包括 java.net 下的部分API(如,Socket、ServerSocket、HttpURLConnection)。
BIO 基于流模型,以同步、阻塞的方式交互(B:Blocking)。
优点:简单、直观。
缺点:IO 效率 和 扩展性 存在局限性,容易成为性能瓶颈。
- InputStream / OutputStream 用于读写 字节
- Reader / Writer 增加了编解码功能,用于读写 字符
- BufferedInputStream / BufferedOutputStream 带缓存区,对批量数据进行一次操作,可以减少对磁盘等硬件的读写频率,提高IO效率
写数据后需要 flush - Closeable 接口提供的 close() 方法可以释放相关资源
如,释放 FileInputStream 所获取的文件描述符(FileDescriptor)
可以利用 try-with-resources 和 try-finally 机制来确保调用了 close()方法
NIO
Java 1.4 引入了 NIO
提供了 Channel、Selector、Buffer 等机制,可以构建多路复用、同步非阻塞的IO程序(N:New、Non-Blocking)。
它提供了更接近操作系统底层的高性能数据操作方式。
JDK 的这部分功能在不同操作系统上实现有较大不同,应在真实的运行环境上测试。如,开发环境是 Windows,部署环境是 Linux,则应以 Linux 环境的调试结果为准。
Java 1.7 引入了 NIO 2(AIO)
提供了异步非阻塞的IO方式(A:Asynchronous)。
缺点:单个请求中数据量较大时,对后续事件的响应会被延迟。所以多路复用适用于大量请求大小有限的场景。
-
Buffer 是高效的数据容器
除 boolean 外,所有原始数据类型都有相应的 Buffer 实现。
-
Channel 用于支持 批量 式 IO
类似 Linux 上的文件描述符,比 File、Socket 更接近操作系统底层。
Channel 可以充分利用操作系统底层机制,获得特定场景的性能优化。如,DMA(Direct Memory Access)。
-
Selector 用于支持 多路复用
它可以监测到注册在 Selector 上的多个 Channel 中,是否有 Channel 处于就绪状态,实现单线程对多 Channel 的高效管理。
针对不同操作系统,Selector 的实现了不同;Linux 上依赖于 Epoll;Windows 上依赖于 iocp
BIO 和 NIO 应用差异示例
此处以 Client-Server Socket 通信为例来说明 NIO 的应用差异。
用 BIO 实现
针对每个来自 Client 的请求,都创建一个对应线程执行,或交由线程池处理。
缺点:扩展性差。大量客户端请求时,产生大量连接,服务端对每个连接的处理需要线程上下文切换,开销过高。
ServerSocket serverSocket = new ServerSocket(80); while (true) { Socket socket = serverSocket.accept(); Thread requestHandler = new Thread(()->{ // 处理来自客户端的请求(socket) }); requestHandler.start(); }
用 NIO 实现
每一个来自 Client 的请求都被汇聚到 Selector,用单线程轮询定位就绪的 Channel,再处理相应的请求。
Selector 类似于一个 调度员
- 同步:每个准备好的 channel 处理是依次进行的;
-
非阻塞:不需要每个连接(channel)都有一个对应的线程在等它就绪 。
只有 select 阶段是阻塞的,可以避免大量客户端连接导致线程频繁切换的问题。
示例代码只注册了一个 Channel。
真实应用中一般会创建 多个 Channel,注册到同一个 Selector,也就是 多路复用。
为了避免单个 Selector (单线程)执行监听任务成为瓶颈,也可以尝试用 多个 Selector。
try (Selector selector = Selector.open(); ServerSocketChannel socketChannel = ServerSocketChannel.open()) { socketChannel.bind(new InetSocketAddress(InetAddress.getLocalHost(), 80)); socketChannel.configureBlocking(false); // 注册到 Selector,并说明关注点(accept) socketChannel.register(selector, SelectionKey.OP_ACCEPT); while (true) { selector.select(); // 等待就绪的 Channel(这是阻塞操作) Set selectionKeys = selector.selectedKeys(); Iterator iter = selectionKeys.iterator(); while (iter.hasNext()) { SelectionKey key = iter.next(); // 处理请求 ServerSocketChannel channel = (ServerSocketChannel)key.channel(); ... iter.remove(); } } } catch (IOException e) { // 处理异常 }
用 AIO 实现
这只是个简单的示例,真实应用中会更复杂
try { AsynchronousServerSocketChannel asyncChannel = AsynchronousServerSocketChannel.open(); asyncChannel.bind(new InetSocketAddress(InetAddress.getLocalHost(), 80)); asyncChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() { @Override public void completed(AsynchronousSocketChannel result, Void attachment) { // 接收下一次连接 asyncChannel.accept(null, this); // 处理本次连接 ... } @Override public void failed(Throwable exc, Void attachement) { // 处理连接失败的情况 } }) } catch (IOException e) { // 处理异常 }
相关推荐
这些操作可以通过Java的图像处理库,如ImageIO或者第三方库(如JavaCV、OpenCV)完成,但`Commons FileUpload`和`Commons IO`则提供了基础的文件操作支持。 总结来说,`commons-fileupload.jar`和`commons-io.jar`...
本文将详细探讨`fastdfs-client-java-1.29-SNAPSHOT.jar`这一核心组件,以及与其相关的`commons-io-2.4.jar`依赖库,`FastDFSClient.java`源代码,和配置文件`fdfs_client.conf`。 首先,`fastdfs-client-java-1.29...
Java IO框架是Java平台中用于处理输入输出操作的核心框架,它包括了一系列的类和接口,为开发者提供了在程序中读取、写入数据的强大能力。Java IO系统的设计基于流(Stream)的概念,流可以视为数据传输的通道,允许...
### 目录多文件上传-JAVA IO流常用详解 #### 概述 本文将详细介绍一个Java程序中的功能模块——如何实现目录多文件上传,并利用Java IO流进行文件复制操作。该功能可以实现在用户选择一个目录后,自动扫描并上传该...
### Java IO流基础知识点 #### 一、IO流概述 - **定义**:在Java中,IO流(Input/Output Streams)是用来处理输入输出的基本工具。流是一种有序的数据集合,通常涉及从源到目的地的数据传输过程。源可以是文件、...
3. **Reactor模式**:Reactor是Java NIO的基础,它是一种基于事件驱动的设计模式,用于高效地处理多个事件源。Reactor模式的核心思想是定义了线程和事件处理器之间的协作机制,其中线程在事件发生时调用相应的事件...
在这个"java-Thread、java-IO.zip"压缩包中,我们关注的是Java中的两个核心概念:线程(Thread)和输入/输出(I/O)。这两个主题在任何Java开发者的学习路径上都是至关重要的。 Java线程是多任务执行的基础,它允许...
输入和输出是编程语言IO库的核心抽象概念。流是一个重要的概念,它将任何数据源或数据接收器表示为一个可以生成或接收数据片段的对象。流隐藏了实际IO设备内部数据处理的细节。在Java库中,IO类按照输入和输出进行了...
1. **Java NIO基础**:Java NIO(New IO)是Java 1.4引入的一个新特性,替代了传统的IO API。NIO的核心概念包括通道(Channels)、缓冲区(Buffers)和选择器(Selectors)。通道代表I/O操作的对象,缓冲区用于存储...
随着对这些基础知识的掌握,你可以继续深入学习Java的高级特性,如集合框架、IO流、数据库连接以及框架技术,如Spring和Hibernate,进一步提升你的编程能力。 总之,“Java技术教程--基础篇”是一份全面的入门资料...
首先,T-io是一个专门为Java设计的网络通信框架,它的核心优势在于其高效的NIO模型,提供了非阻塞I/O操作,这使得它在处理大量并发连接时表现出色。T-io提供了一套完整的API和工具,使得开发者能够快速地搭建起基于...
"commons-io-2.4.jar"是这个库的一个版本,包含了各种实用的工具类,方便开发者处理文件、流、读写操作和其他I/O相关的任务。在Java SE环境中,它是一个非常受欢迎的补充,特别是对于那些需要进行复杂I/O操作的项目...
在本学习案例中,我们关注的是Java的IO流和Socket技术,这些是实现客户端-服务器通信的基础。IO流用于数据的输入输出操作,而Socket则是网络通信的桥梁。 首先,让我们深入了解Java的IO流。IO流在Java中被广泛用于...
### JAVA IO-NIO 详解 #### 一、IO与NIO概述 在Java开发中,输入/输出(IO)操作是程序与外部环境交互的重要环节。通过IO操作,程序可以读取外部数据或向外部环境输出数据。Java的IO体系自Java 1.0以来就一直存在...
Java.IO(Input/Output)是Java...通过这29页的课件,学习者将能掌握Java IO的基础知识,为后续的高级IO操作,如网络编程和数据库交互奠定坚实基础。在实际开发中,熟练运用Java IO可以有效提升程序的效率和灵活性。
《Java核心技术-卷2》是Java开发者不可或缺的参考书籍,主要涵盖了Java开发中的高级特性,这些特性虽然在标题中没有全部列出,但根据描述,我们可以推测主要包括IO(输入/输出)、文件系统操作、正则表达式处理、...
非阻塞I/O和选择器的使用可以显著提高网络应用的性能,这部分可能涉及FileInputStream、FileOutputStream、BufferedReader、BufferedWriter等基础IO类,以及Selector、Channel和Pipe的NIO操作。 总的来说,《JAVA...
Java中的IO流是进行输入/输出操作的核心机制,它允许程序与各种数据源(如文件、网络连接、内存缓冲区等)进行数据交换。在Java中,IO流被设计为一个层次化的体系结构,便于理解和使用。这个体系结构是根据流的方向...
在本篇文章中,我们将深入探讨Apache Commons IO 2.6中的核心概念和技术。 1. **文件操作**: - `FileUtils`: 提供了一系列静态方法,用于执行复杂的文件操作,如复制、移动、删除、比较、读取和写入文件内容。 -...
由于这个版本被验证为无误,开发者可以信任它的稳定性和可靠性,从而更专注于应用程序的核心逻辑,而无需担心基础的I/O操作问题。 在实际开发中,Apache Commons IO 通常与其他流行的开源库结合使用,如Spring框架...