- Java NIO 教程
- Java NIO - 首頁
- Java NIO - 概述
- Java NIO - 環境設定
- Java NIO vs JAVA IO
- Java NIO - 通道
- Java NIO - 檔案通道
- Java NIO - 資料報通道
- Java NIO - 套接字通道
- Java NIO - 伺服器套接字通道
- Java NIO - 散射
- Java NIO - 收集
- Java NIO - 緩衝區
- Java NIO - 選擇器
- Java NIO - 管道
- Java NIO - 路徑
- Java NIO - 檔案
- Java NIO - 非同步檔案通道
- Java NIO - 字元集
- Java NIO - 檔案鎖
- Java NIO 有用資源
- Java NIO - 快速指南
- Java NIO - 有用資源
- Java NIO - 討論
Java NIO - 非同步檔案通道
眾所周知,Java NIO 支援併發和多執行緒,允許我們同時處理不同的通道。因此,Java NIO 包中負責此功能的 API 是 AsynchronousFileChannel,它定義在 NIO 通道包下。因此,AsynchronousFileChannel 的限定名稱為java.nio.channels.AsynchronousFileChannel。
AsynchronousFileChannel 與 NIO 的 FileChannel 類似,區別在於此通道允許非同步執行檔案操作,不像同步 I/O 操作那樣,執行緒進入操作並等待請求完成。因此,非同步通道可以安全地被多個併發執行緒使用。
在非同步操作中,執行緒將請求傳遞給作業系統的核心來完成,而執行緒繼續處理其他任務。核心完成任務後,它會向執行緒發出訊號,然後執行緒確認訊號並中斷當前任務,根據需要處理 I/O 任務。
為了實現併發,此通道提供兩種方法,一種是返回java.util.concurrent.Future 物件,另一種是將型別為java.nio.channels.CompletionHandler的物件傳遞給操作。
我們將透過示例逐一瞭解這兩種方法。
Future 物件 - 在此方法中,從通道返回 Future 介面的一個例項。在 Future 介面中,有一個get()方法,它返回非同步處理的操作狀態,據此可以決定其他任務的進一步執行。我們還可以透過呼叫其isDone方法來檢查任務是否已完成。
示例
以下示例顯示瞭如何使用 Future 物件非同步執行任務。
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();
}
}
輸出
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?
CompletionHandler -
這種方法非常簡單,因為它使用 CompletionHandler 介面並重寫其兩個方法:一個是completed()方法,在 I/O 操作成功完成時呼叫;另一個是failed()方法,在 I/O 操作失敗時呼叫。在此方法中,建立一個處理程式來使用非同步 I/O 操作的結果,因為只有在任務完成後,處理程式才會執行其函式。
示例
以下示例顯示瞭如何使用 CompletionHandler 非同步執行任務。
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();
}
}
輸出
Input string: Content to be written to the file. Async Task completed and 34 bytes are written. File contents: Content to be written to the file.