FileChannel의 read() write()는 입출력작업을 하는 동안 블로킹이 된다.
그래서 UI 및 이벤트를 처리하는 스레드에서 이 메소드들을 호출하면 블로킹되는 동안 UI갱신이나 이벤트 처리를 할 수 없어 작업 스레드를 생성해서 처리해야한다.
그래서 NIO에서 불특정 다수 파일 및 대용량 파일의 입출력 작업을 위해 비동기 파일 채널(AsynchronousFileChannel)을 별도로 제공함
1. AsynchronousFileChannel 생성과 닫기
- AsynchronousFileChannel은 두 가지 정적 메소드인 open()을 호출하여 얻을 수 있다.
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(Path file, OpenOption... options);
AsynchronousFileChannel은 내부적으로 생성되는 기본 스레드풀을 이용해서 스레드를 관리한다.
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(Path file, Set<? extends OpenOption> options, ExecutorService executor, FileAttribute<?>.args.. attrs);
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path,
EnumSet.of(StandardOpenOption.CREATE, StandardOpenOption.WRITE), executorService);
- 채널 종료
fileChannel.close();
2. 파일 읽기와 쓰기
- AsynchronousFileChannel이 생성되었다면 read()와 write() 메서드를 이용하여 입출력할 수 있다.
- 읽기 : fileChannel.read(ByteBuffer dst, long position, A attachment, CompletionHandler<Integer, A> handler);
- 쓰기 : fileChannel.write(ByteBuffersrc, long position, A attachment, CompletionHandler<Integer, A> handler);
CompletionHandler<Integer, A> 구현 객체는 비동기 작업이 정상적으로 완료된 경우와 예외발생으로 실패된 경우에 자동 콜백되는 2가지 메서드를 가지고 있어야 한다.
complated() : 정상적으로 완료된경우
failed() : 예외작업으로 실패된 경우
ex) 파일 쓰기
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
Path path = Paths.get("d:/hello.txt");
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path,
EnumSet.of(StandardOpenOption.CREATE, StandardOpenOption.WRITE), executorService);
// 파일에 저장할 데이터를 byteBuffer에 저장
Charset charset = Charset.defaultCharset();
ByteBuffer byteBuffer = charset.encode("hello Java\n");
// 첨부 객체 생성
class Attachment {
Path path;
AsynchronousFileChannel fileChannel;
}
Attachment attachment = new Attachment();
attachment.path = path;
attachment.fileChannel = fileChannel;
// CompletionHandler 객체 생성
CompletionHandler<Integer, Attachment> completionHandler = new CompletionHandler<Integer, Attachment>() {
@Override
public void completed(Integer result, Attachment attachment) {
System.out.println(attachment.path.getFileName() + " : " + result + "byte written : "
+ Thread.currentThread().getName());
try {
attachment.fileChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void failed(Throwable exec, Attachment attachment) {
exec.printStackTrace();
try {
attachment.fileChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
};
fileChannel.write(byteBuffer, 0, attachment, completionHandler);
ex) 파일 읽기
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
Path path = Paths.get("d:/c85dacbb51fa430bb2c25c025e8ea2dcU2011944.jpg");
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, EnumSet.of(StandardOpenOption.READ),
executorService);
ByteBuffer buffer = ByteBuffer.allocate((int) fileChannel.size() * 4);
class Attachment {
Path path;
AsynchronousFileChannel fileChannel;
ByteBuffer buffer;
}
Attachment attachment = new Attachment();
attachment.path = path;
attachment.fileChannel = fileChannel;
attachment.buffer = buffer;
CompletionHandler<Integer, Attachment> completionHandler = new CompletionHandler<Integer, Attachment>() {
@Override
public void completed(Integer result, Attachment attachment) {
System.out.println(attachment.path.getFileName() + " : " + result + "byte written : "
+ Thread.currentThread().getName());
try {
attachment.fileChannel.close();
} catch (Exception e) {
}
}
@Override
public void failed(Throwable exc, Attachment attachment) {
exc.printStackTrace();
try {
attachment.fileChannel.close();
} catch (Exception e) {
}
}
};
fileChannel.read(buffer, 0, attachment, completionHandler);
executorService.shutdown();
'Language > Java' 카테고리의 다른 글
volatile 키워드 (0) | 2017.04.13 |
---|---|
NIO TCP blocking channel 소켓서버 & 클라이언트 (0) | 2017.03.30 |
NIO (0) | 2017.03.29 |
[JAVA NIO] WatchService(와치서비스) (0) | 2017.03.24 |
규칙 2. 생성자 인자가 많을 때는 Builder 패턴 적용을 고려하라 (0) | 2017.01.19 |