자바 NIO-AsynchronousFileChannel

Java NIO는 동시성 및 멀티 스레딩을 지원하여 동시에 여러 채널을 동시에 처리 할 수 ​​있다는 것을 알고 있으므로 Java NIO 패키지에서이를 담당하는 API는 NIO channels 패키지에 정의 된 AsynchronousFileChannel입니다. AsynchronousFileChannel의 경우 java.nio.channels.AsynchronousFileChannel.

AsynchronousFileChannel은 스레드가 작업에 들어가서 요청이 완료 될 때까지 대기하는 동기 I / O 작업과 달리이 채널을 사용하면 파일 작업을 비동기 적으로 실행할 수 있다는 점을 제외하면 NIO의 FileChannel과 유사합니다. 따라서 비동기 채널은 사용하기에 안전합니다. 여러 동시 스레드에 의해.

비동기식에서 요청은 스레드가 운영 체제의 커널로 전달하여 스레드가 다른 작업을 계속 처리하는 동안 완료됩니다. 커널 작업이 완료되면 스레드에 신호를 보내고 스레드는 신호를 확인하고 현재 작업을 중단하고 필요에 따라 I / O 작업.

동시성을 달성하기 위해이 채널은 하나를 반환하는 두 가지 접근 방식을 제공합니다. java.util.concurrent.Future object 다른 하나는 유형의 객체를 작업에 전달하는 것입니다. java.nio.channels.CompletionHandler.

우리는 예제를 통해 하나씩 두 가지 접근 방식을 이해할 것입니다.

  • Future Object −이 경우 Future Interface의 인스턴스가 채널에서 반환됩니다. 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?
  • 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.