Io, nio 차이
입출력방식 : 스트림방식 , 채널방식
버퍼방식 : 논 버퍼, 버퍼
비동기방식 : 지원안함, 지원
블로킹/논블로킹 방식 : 블로킹방식, 블로킹/논블로킹모두 지원
스트림 vs 채널
스트림 : 입력을 하기위해 입력 스트림을 생성하고 출력을 하기위해 출력 스트림을 생성해야함
NIO(채널) : 채널은 양방향으로 입력과 출력이 가능. 입출력을 하기 위해 별도의 채널을 만들 필요가 없음.
버퍼 vs 논버퍼
IO에서는 스트림이 1바이트를 쓰면 입력스트림이 1바이트를 읽는다. (이런 시스템은 대체로 느림)
그래서 버퍼를 이용하여 복수 개의 바이트를 한꺼번에 입력받고 출력하는 것이 빠른 성능을 냄(보조 스트림 BufferedInputStream, BufferedOutputStream)
IO는 스트림에서 읽은 데이터를 즉시 처리하므로 데이터를 별도로 지정하지 않으면 입력된 데이터의 위치를 이동해가면서 자유롭게 이용할 수 없다.
NIO는 기본적으로 버퍼를 이용하여 입출력을 하므로 IO보다 입출력 성능이 좋음.
채널을 버퍼에 저장된 데이터를 출력하고 입력된 데이터를 버퍼에 저장
NIO는 읽은 데이터를 무조건 버퍼에 저장하기 때문에 버퍼 내에서 데이터의 위치를 이동해 가면서 필요한 부분만 읽고 쓸 수 있다.
블로킹 vs 논블로킹
IO블로킹은 입출력 스트림의 read(), write() 메소드를 호출하면 데이터가 입력하기 전까지 스레드가 블로킹(대기상태)가 된다. 블로킹이 되면 다른 일을 할 수 없고 블로킹을 빠저나오기 위해 인터럽트도 할 수 없다. 블로킹을 빠져나오는 유일한 방법은 스트림을 다는 것이다.
NIO 는 블로킹과 Non-blocking 특징을 모두 가지고 있다. IO블로킹과 차이점은 NIO블로킹은 스레드를 인터럽트함으로써 빠져나올 수가 있다. 논블로킹은 입출력 작업시 스레드가 블로킹되지 않는 다는 것을 말함.
논블로킹은 작업 준비가 완료된 채널(지금 바로 읽고 쓸 수 있는 상태)만 선택해서 작업 스레드가 처리하기 때문에 작업 스레드가 블로킹 되지 않는다.
NIO의 핵심 객체는 멀티플렉서와 셀렉터이다. 셀렉터는 복수개의 채널 중에서 준비가 완료된 채널을 선택하는 방법을 제공
Buffer(버퍼)
- NIO에서는 데이터를 입출력하기 위해 항상 버퍼를 사용. 버퍼는 읽고 쓰기가 가능한 메모리 배열이다.
Buffer는 저장되는 데이터 타입에 따라 분류될 수 있고 어떤 메모리를 사용하느냐에 따라 다이렉트(Direct)와 non다이렉트(NonDirect)로 분류할 수 있다.
1.데이터 타입에 따른 버퍼
- 저장되는 데이터 타입에 따라 별도의 클래스를 제공한다.
2.넌다이렉트와 다이렉트 버퍼
- 버퍼가 사용하는 메모리 위치에 따라서 Non-direct와 direct 버퍼로 분류
- Non-direct버퍼는 JVM이 관리하는 힙 메모리 공간을 이용하는 버퍼
- Direct 버퍼는 운영체제가 관리하는 메모리 공간을 이용하는 버퍼
특징
구분 |
Non-direct |
Direct |
사용하는 메모리공간 |
JVM 힙 메모리 |
운영체제의 메모리 |
버퍼 생성시간 |
버퍼 생성이 빠름 |
버퍼 생성이 느림(Native 호출) |
버퍼의 크기 |
작다 |
크다(큰 데이터를 처리할 때 유리) |
입출력성능 |
낮다 |
높다(입출력이 빈번할 때 유리) |
다이렉트 버퍼는 버퍼 생성을 운영체제의 Native c함수를 호출하고 다양한 처리를 하기 때문에 상대적으로 버퍼 생성이 느리다. 그렇기 때문에 자주 생성하기 보다는 한 번 생성해 놓고 재사용하는 것이 적합.
Non다이렉트 버퍼는 JVM의 제한된 힙 메모리를 사용하므로 버퍼의 크기를 크게 잡을 수 없고, 다이렉트 버퍼는 운영체제 내에서 할당 받기 때문에 버퍼의 크기를 크게 잡을 수 있다.
버퍼 생성
- non-direct는 allocate()와 wrap() 메소드를 호출하여 이용하고, direct는 allocateDirect() 메서드를 이용한다.
ByteBuffer ndb = ByteBuffer.allocate(200 * 1024 * 1024); //non-direct buffer 생성
ByteBuffer buffer = ByteBuffer.wrap(new byte[1024]); //non-direct buffer 생성
ByteBuffer db = ByteBuffer.allocateDirect(200 * 1024 * 1024); //direct buffer 생성
Buffer의 위치속성
속성 |
설명 |
position |
현재 읽거나 쓰는 위치값이다. 인덱스 값이기 때문에 0부터 시작하며, limit보다 큰 값을 가질 수 없다. 만약 position과 limit의 값이 같아진다면 더 이상 데이터를 쓰거나 읽을 수 없다. |
limit |
버퍼에서 읽거나 쓸 수 있는 위치의 한계를 나타낸다. 이 값은 capacity보다 작거나 같은 값을 가진다. 최초에 버퍼를 만들었을 때는 capacity와 같은 값을 가진다. |
capacity |
버퍼의 최대 데이터 개수(메모리크기)를 나타낸다. 인덱스 값이 아니라 수량임을 주의 |
mark |
Reset() 메서드를 실행했을 때 돌아오는 위치를 지정하는 인덱스로써 mark() 메서드로 지정할 수 있다. 주의할 점은 반드시 position 이하의 값으로 지정해줘야한다. position이나 limit 값이 makr 값보다 작은 경우, mark는 자동제거된다. Mark가 없는 상태에서 reset() 메서드를 호출하면 InvalidMarkException이 발생한다. |
- position, limit, capacity, mark 속성의 크기 관계
Mark는 position보다 클 수 없고, position은 limit보다 클 수 없으며, limit는 capacity보다 클 수 없다.
0 <= mark <= position <= limit <= capacity
'Language > Java' 카테고리의 다른 글
NIO TCP blocking channel 소켓서버 & 클라이언트 (0) | 2017.03.30 |
---|---|
비동기 파일채널 (0) | 2017.03.29 |
[JAVA NIO] WatchService(와치서비스) (0) | 2017.03.24 |
규칙 2. 생성자 인자가 많을 때는 Builder 패턴 적용을 고려하라 (0) | 2017.01.19 |
규칙 1. 생성자대신 정적 팩터리 메서드를 사용할 수 없는지 생각해 보라 (0) | 2017.01.19 |