Java NIO - AsynchronousFileChannel
อย่างที่เราทราบกันดีว่า Java NIO รองรับการทำงานพร้อมกันและมัลติเธรดซึ่งช่วยให้เราจัดการกับแชนเนลต่างๆพร้อมกันได้ในเวลาเดียวกันดังนั้น API ที่รับผิดชอบสิ่งนี้ในแพ็คเกจ Java NIO คือ AsynchronousFileChannel ซึ่งกำหนดไว้ภายใต้แพ็คเกจช่อง NIO ดังนั้นชื่อที่ถูกต้อง สำหรับ AsynchronousFileChannel คือ java.nio.channels.AsynchronousFileChannel.
AsynchronousFileChannel คล้ายกับ FileChannel ของ NIO ยกเว้นว่าช่องสัญญาณนี้จะเปิดใช้งานไฟล์เพื่อดำเนินการแบบอะซิงโครนัสซึ่งแตกต่างจากการดำเนินการ I / O แบบซิงโครนัสที่เธรดเข้าสู่การดำเนินการและรอจนกว่าการร้องขอจะเสร็จสมบูรณ์ดังนั้นช่องสัญญาณแบบอะซิงโครนัสจึงปลอดภัยสำหรับการใช้งาน โดยหลายเธรดพร้อมกัน
ในแบบอะซิงโครนัสคำร้องขอจะถูกส่งผ่านเธรดไปยังเคอร์เนลของระบบปฏิบัติการเพื่อทำให้เสร็จในขณะที่เธรดยังคงดำเนินการกับงานอื่นเมื่องานของเคอร์เนลเสร็จสิ้นแล้วจะส่งสัญญาณไปยังเธรดจากนั้นเธรดจะรับสัญญาณและขัดจังหวะงานปัจจุบันและประมวลผล งาน I / O ตามต้องการ
เพื่อให้บรรลุการทำงานพร้อมกันช่องทางนี้มีสองแนวทางซึ่งรวมถึงวิธีหนึ่งที่ส่งกลับ a java.util.concurrent.Future object และอื่น ๆ คือการส่งผ่านไปยังการดำเนินการวัตถุประเภท java.nio.channels.CompletionHandler.
เราจะเข้าใจทั้งสองแนวทางด้วยความช่วยเหลือของตัวอย่างทีละตัวอย่าง
Future Object - ในอินสแตนซ์ของอินเทอร์เฟซในอนาคตจะถูกส่งคืนจากช่องสัญญาณในอินเทอร์เฟซในอนาคตมี get() วิธีการที่ส่งคืนสถานะของการดำเนินการที่ได้รับการจัดการแบบอะซิงโครนัสบนพื้นฐานของการตัดสินใจดำเนินการงานอื่น ๆ ต่อไปนอกจากนี้เรายังสามารถตรวจสอบว่างานเสร็จสมบูรณ์หรือไม่โดยเรียก isDone วิธี.
ตัวอย่าง
ตัวอย่างต่อไปนี้แสดงวิธีการใช้วัตถุในอนาคตและงานแบบอะซิงโครนัส
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?
Completion Handler -
วิธีนี้ค่อนข้างง่ายเนื่องจากเราใช้อินเทอร์เฟซ 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.