在介绍并发 IO 前,我们先看看什么是并发。并发是指在同一时间段内,多个任务或操作在宏观上同时进行的现象。以下从不同角度为你详细解释:
操作系统角度:并发是指在一个操作系统中,有多个进程或线程在同一时间段内都处于运行状态,但在任意一个时刻,实际上只有一个进程或线程在处理器上执行。操作系统通过时间片轮转、优先级调度等算法,让多个进程或线程交替使用处理器资源,使得它们在宏观上看起来是同时运行的。例如,在一台计算机上同时打开多个应用程序,如浏览器、音乐播放器、文档编辑器等,这些应用程序的进程就是并发执行的。
编程语言角度:在编程语言中,并发通常是通过多线程技术来实现的。多线程编程允许在一个程序中创建多个线程,每个线程可以独立执行不同的代码块,从而实现并发执行。
数据库角度:并发指的是多个数据库事务同时对数据库进行操作的情况。数据库系统需要通过并发控制机制来确保多个事务的并发执行不会导致数据不一致或其他问题。常见的并发控制技术包括锁机制、事务隔离级别等。例如,当多个用户同时对一个数据库表进行插入、更新或删除操作时,数据库系统需要通过并发控制来保证数据的一致性和完整性。
注意,并发的目的是提高系统的资源利用率和响应速度,让多个任务能够在同一时间段内尽可能高效地执行,从而提高整个系统的性能和吞吐量。但并发也会带来一些问题,如资源竞争、数据不一致、死锁等,需要通过合理的设计和技术手段来解决。
有时,你可能需要同时处理输入(Input)和输出(Output)。换句话说,可能需要多个线程处理输入和输出。例如,你可能有一个应用程序需要处理磁盘上的大量文件。这可以并行处理,并获得性能提升。或者,你可能有一个服务器,如网络服务器或聊天服务器,需要接收许多单独的连接和请求。这些请求也可以并行处理,从而提高性能。如下图:
上图中,假如存在10万份文件需要处理,此时就需要开启N多个线程同时去处理这些文件,这样可以提升处理速度。
注意,如果你需要并行 IO,你应该注意以下几个问题:
(1)不应让多个线程同时从 InputStream 或 Reader 读取数据。也不应让多个线程同时向 OutputStream 或 Writer 写入数据。如果这样做,就无法保证每个线程将读取多少输入内容,也无法保证线程按什么顺序将数据写入输出流。
(2)如果多个线程按顺序使用一个 InputStream、OutputStream、Reader 或 Writer,就可以让多个线程使用。例如,你可以让一个线程从输入中确定请求的类型,然后将其交给相应的线程进一步处理。这样做是可行的,因为对 Stream/Reader 的访问是按顺序进行的。注意:在线程间传输流的代码应适当同步 synchronized。
📢 注意:在 Java NIO 中,通过 Selector(选择器)可以实现一个线程从多个通道(Channel)读取数据或向多个通道写入数据。Selector 允许单线程处理多个 Channel。如果你的应用打开了多个连接(通道),但每个连接的流量都很低,使用 Selector 就会很方便。本教程不介绍关于 Java NIO 相关的知识,将在单独到教程中介绍。