Java Nio 简明教程
Java NIO - AsynchronousFileChannel
众所周知,Java NIO 支持并发和多线程,这允许我们在同一时间同时处理不同的通道。因此,在 Java NIO 包中负责此操作的 API 是 AsynchronousFileChannel,它在 NIO 通道包下定义。因此 AsynchronousFileChannel 的限定名称为 java.nio.channels.AsynchronousFileChannel 。
As we know that Java NIO supports concurrency and multi-threading which allows us to deal with different channels concurrently at same time.So the API which is responsible for this in Java NIO package is AsynchronousFileChannel which is defined under NIO channels package.Hence qualified name for AsynchronousFileChannel is java.nio.channels.AsynchronousFileChannel.
AsynchronousFileChannel 类似于 NIO 的 FileChannel,但不同的是,此通道允许文件操作异步执行,而不像同步 I/O 操作中线程会进入操作并等待请求完成。因此,异步通道可供多个并发线程安全使用。
AsynchronousFileChannel is similar to that of the NIO’s FileChannel,except that this channel enables file operations to execute asynchronously unlike of synchronous I/O operation in which a thread enters into an action and waits until the request is completed.Thus asynchronous channels are safe for use by multiple concurrent threads.
在异步中,请求由线程传递给操作系统的内核以完成,而线程继续处理另一项工作。一旦内核完成工作,它就会向线程发出信号,然后线程确认信号并中断当前工作并根据需要处理 I/O 工作。
In asynchronous the request is passed by thread to the operating system’s kernel to get it done while thread continues to process another job.Once the job of kernel is done it signals the thread then the thread acknowledged the signal and interrupts the current job and processes the I/O job as needed.
为了实现并发,此通道提供了两种方法,其中一种是返回 java.util.concurrent.Future object ,另一种是将 java.nio.channels.CompletionHandler 类型对象传递给操作。
For achieving concurrency this channel provides two approaches which includes one as returning a java.util.concurrent.Future object and other is Passing to the operation an object of type java.nio.channels.CompletionHandler.
我们将逐一借助示例了解这两种方法。
We will understand both the approaches with help of examples one by one.
-
Future Object − In this an instance of Future Interface is returned from channel.In Future interface there is get() method which returns the status of operation that is handled asynchronously on the basis of which further execution of other task could get decided.We can also check whether task is completed or not by calling its isDone method.
Example
以下示例显示如何使用 Future 对象和异步任务。
The following example shows the how to use Future object and to task asynchronously.
package com.java.nio;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
public class FutureObject {
public static void main(String[] args) throws Exception {
readFile();
}
private static void readFile() throws IOException, InterruptedException, ExecutionException {
String filePath = "D:fileCopy.txt";
printFileContents(filePath);
Path path = Paths.get(filePath);
AsynchronousFileChannel channel =AsynchronousFileChannel.open(path, StandardOpenOption.READ);
ByteBuffer buffer = ByteBuffer.allocate(400);
Future<Integer> result = channel.read(buffer, 0); // position = 0
while (! result.isDone()) {
System.out.println("Task of reading file is in progress asynchronously.");
}
System.out.println("Reading done: " + result.isDone());
System.out.println("Bytes read from file: " + result.get());
buffer.flip();
System.out.print("Buffer contents: ");
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());
}
System.out.println(" ");
buffer.clear();
channel.close();
}
private static void printFileContents(String path) throws IOException {
FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr);
String textRead = br.readLine();
System.out.println("File contents: ");
while (textRead != null) {
System.out.println(" " + textRead);
textRead = br.readLine();
}
fr.close();
br.close();
}
}
Output
File contents:
To be or not to be?
Task of reading file is in progress asynchronously.
Task of reading file is in progress asynchronously.
Reading done: true
Bytes read from file: 19
Buffer contents: To be or not to be?
-
Completion Handler − This approach is pretty simple as in this we uses CompletionHandler interface and overrides its two methods one is completed() method which is invoked when the I/O operation completes successfully and other is failed() method which is invoked if the I/O operations fails.In this a handler is created for consuming the result of an asynchronous I/O operation as once a task is completed then only the handler has functions that are executed.
Example
以下示例显示如何使用 CompletionHandler 进行异步任务。
The following example shows the how to use CompletionHandler to task asynchronously.
package com.java.nio;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousFileChannel;
import java.nio.channels.CompletionHandler;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
public class CompletionHandlerDemo {
public static void main (String [] args) throws Exception {
writeFile();
}
private static void writeFile() throws IOException {
String input = "Content to be written to the file.";
System.out.println("Input string: " + input);
byte [] byteArray = input.getBytes();
ByteBuffer buffer = ByteBuffer.wrap(byteArray);
Path path = Paths.get("D:fileCopy.txt");
AsynchronousFileChannel channel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
CompletionHandler handler = new CompletionHandler() {
@Override
public void completed(Object result, Object attachment) {
System.out.println(attachment + " completed and " + result + " bytes are written.");
}
@Override
public void failed(Throwable exc, Object attachment) {
System.out.println(attachment + " failed with exception:");
exc.printStackTrace();
}
};
channel.write(buffer, 0, "Async Task", handler);
channel.close();
printFileContents(path.toString());
}
private static void printFileContents(String path) throws IOException {
FileReader fr = new FileReader(path);
BufferedReader br = new BufferedReader(fr);
String textRead = br.readLine();
System.out.println("File contents: ");
while (textRead != null) {
System.out.println(" " + textRead);
textRead = br.readLine();
}
fr.close();
br.close();
}
}