Understanding Java I/O: BIO, NIO, AIO and Implementing I/O Multiplexing
This article explains the concepts of blocking (BIO), non‑blocking (NIO) and asynchronous (AIO) I/O in Java, introduces the principle of I/O multiplexing, provides a complete Java example with server and client code, and compares system calls like select, poll, and epoll.
Since the early days of the Internet, topics such as BIO and NIO have been constantly discussed; this article aims to give a thorough understanding of these concepts, illustrate the underlying I/O principles, and present a Java implementation of I/O multiplexing.
What is I/O? Any network request or disk read is an I/O operation, meaning data must be transferred through a medium; the flow goes from the peripheral (e.g., network card) to kernel space, then to user space (JVM), and finally to the application.
The article shows diagrams of a network read and explains where blocking occurs. BIO (synchronous blocking I/O) blocks the program until data moves from the network card to kernel space and then to user space. Starting with Java 1.4, NIO reduces blocking by returning immediately when data is not yet in kernel space, only blocking when the program reads after the kernel has the data.
I/O multiplexing is introduced as a way to handle many connections with a single thread, avoiding the overhead of creating and switching many threads. Multiplexing (or "multiplexing") means tracking the state of each I/O stream in one thread to improve throughput.
The article provides a complete Java example that implements I/O multiplexing using ServerSocketChannel in non‑blocking mode. The server registers new connections, selects ready sockets, and processes them in a continuous while (true) loop. Key methods such as register , selectedKeys , and handle are explained.
Key points of the implementation:
Define register to add new SocketChannel objects to a publicKeys set.
Define selectedKeys to iterate over publicKeys and collect channels whose validOps() & OP_READ is non‑zero, indicating they are ready for reading.
Use a while (true) loop to continuously process readable sockets, achieving I/O multiplexing.
A simple client example is also provided, showing how to open a non‑blocking SocketChannel , read user input, and write it to the server.
The article then discusses system‑level I/O multiplexing mechanisms such as select , poll , and epoll . It presents the C prototype of select and explains its parameters ( nfds , readfds , writefds , exceptfds , timeout ). It notes that poll removes the 1024‑descriptor limit of select , while epoll further improves performance by delivering only changed events without full scans.
In summary, whether using custom Java code or OS system calls, the goal is the same: to enable a single thread to manage multiple I/O streams efficiently, which is the essence of I/O multiplexing.
Full-Stack Internet Architecture
Introducing full-stack Internet architecture technologies centered on Java
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.