거꾸로 바라본 세상
Published 2017. 3. 29. 17:33
비동기 파일채널 Language/Java
반응형
비동기 파일채널


 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();


반응형
profile

거꾸로 바라본 세상

@란지에。

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!