← Back to Advanced Java Course | Chapter 13: Java NIO | Lesson 3 of 5

Java Async File I/O

AsynchronousFileChannel lets a program start a read or write and continue other work immediately, using either a Future or a CompletionHandler to be notified once the operation completes.

What is Asynchronous File I/O?

Asynchronous file I/O lets a program start a read or write operation and continue doing other work immediately, being notified only once the operation actually completes, instead of blocking the calling thread the entire time.

Example: What is Asynchronous File I/O?

java
// Define the class Main
public class Main {
	// Program entry point: the JVM starts running here
	public static void main(String[] args) {
		// Print a line to the console
		System.out.println("Async I/O starts an operation and continues, notified only on completion");
	}
}

AsynchronousFileChannel Basics

AsynchronousFileChannel, part of NIO.2, is opened much like a regular FileChannel but supports non-blocking reads and writes, and like other NIO channels it still reads into and writes from a ByteBuffer.

Example: AsynchronousFileChannel Basics

java
// Import java.nio.channels.AsynchronousFileChannel so it can be used by its short name
import java.nio.channels.AsynchronousFileChannel;
// Import java.nio.file.* so it can be used by its short name
import java.nio.file.*;
// Define the class Main
public class Main {
	// Program entry point: the JVM starts running here
	public static void main(String[] args) throws Exception {
		Path file = Files.createTempFile("demo", ".txt");
		AsynchronousFileChannel channel = AsynchronousFileChannel.open(file, StandardOpenOption.READ);
		// Print a line to the console
		System.out.println("Opened: " + channel.isOpen());
		channel.close();
		Files.delete(file);
	}
}

Reading Asynchronously with a Future

Calling read on an AsynchronousFileChannel returns a Future immediately, and the calling thread can continue running other code, only blocking if and when it later calls get() to retrieve the actual result.

Example: Reading Asynchronously with a Future

java
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.*;
import java.nio.ByteBuffer;
import java.util.concurrent.Future;
public class Main {
	public static void main(String[] args) throws Exception {
		Path file = Files.createTempFile("demo", ".txt");
		Files.writeString(file, "hello");
		AsynchronousFileChannel channel = AsynchronousFileChannel.open(file, StandardOpenOption.READ);
		ByteBuffer buffer = ByteBuffer.allocate(5);
		Future<Integer> future = channel.read(buffer, 0); // returns immediately
		future.get(); // blocks only here, when the result is needed
		System.out.println(new String(buffer.array()));
		channel.close();
		Files.delete(file);
	}
}

Reading Asynchronously with a CompletionHandler

A CompletionHandler is an alternative to Future that avoids blocking entirely: its completed method is called automatically with the result when the operation succeeds, and its failed method is called if the operation encounters an error.

Example: Reading Asynchronously with a CompletionHandler

java
// Import java.nio.channels.* so it can be used by its short name
import java.nio.channels.*;
// Import java.nio.file.* so it can be used by its short name
import java.nio.file.*;
import java.nio.ByteBuffer;
// Define the class Main
public class Main {
	// Program entry point: the JVM starts running here
	public static void main(String[] args) throws Exception {
		Path file = Files.createTempFile("demo", ".txt");
		Files.writeString(file, "data");
		AsynchronousFileChannel channel = AsynchronousFileChannel.open(file, StandardOpenOption.READ);
		ByteBuffer buffer = ByteBuffer.allocate(4);
		channel.read(buffer, 0, null, new CompletionHandler<Integer, Void>() {
			public void completed(Integer result, Void attachment) {
				// Print a line to the console
				System.out.println("Read complete: " + new String(buffer.array()));
			}
			public void failed(Throwable exc, Void attachment) {
				// Print a line to the console
				System.out.println("Failed: " + exc.getMessage());
			}
		});
		Thread.sleep(100);
		channel.close();
		Files.delete(file);
	}
}

Writing Asynchronously

Asynchronous writes work the same way as asynchronous reads, returning a Future or accepting a CompletionHandler, and the operation is only considered complete once the data has actually been written to the underlying file.

Example: Writing Asynchronously

java
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.*;
import java.nio.ByteBuffer;
public class Main {
	public static void main(String[] args) throws Exception {
		Path file = Files.createTempFile("demo", ".txt");
		AsynchronousFileChannel channel = AsynchronousFileChannel.open(file, StandardOpenOption.WRITE);
		ByteBuffer buffer = ByteBuffer.wrap("async write".getBytes());
		channel.write(buffer, 0).get(); // complete once actually written
		channel.close();
		System.out.println(Files.readString(file));
		Files.delete(file);
	}
}
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Letting main finish before the asynchronous operation completes, so the result is never printed.
  2. Calling future.get() immediately after starting the read, which blocks and removes the benefit of async I/O.
  3. Forgetting that async read and write need a file position argument and that a buffer must be flipped before its data is used.
🔒

Chapter Quiz — Complete all 5 topics to unlock

0/5 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.