거꾸로 바라본 세상
Published 2017. 3. 29. 16:10
NIO Language/Java
반응형

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-directdirect 버퍼로 분류

- Non-direct버퍼는 JVM이 관리하는 힙 메모리 공간을 이용하는 버퍼

- Direct 버퍼는 운영체제가 관리하는 메모리 공간을 이용하는 버퍼

 

특징

구분

Non-direct

Direct

사용하는 메모리공간

JVM 힙 메모리

운영체제의 메모리

버퍼 생성시간

버퍼 생성이 빠름

버퍼 생성이 느림(Native 호출)

버퍼의 크기

작다

크다(큰 데이터를 처리할 때 유리)

입출력성능

낮다

높다(입출력이 빈번할 때 유리)

다이렉트 버퍼는 버퍼 생성을 운영체제의 Native c함수를 호출하고 다양한 처리를 하기 때문에 상대적으로 버퍼 생성이 느리다. 그렇기 때문에 자주 생성하기 보다는 한 번 생성해 놓고 재사용하는 것이 적합.

Non다이렉트 버퍼는 JVM의 제한된 힙 메모리를 사용하므로 버퍼의 크기를 크게 잡을 수 없고, 다이렉트 버퍼는 운영체제 내에서 할당 받기 때문에 버퍼의 크기를 크게 잡을 수 있다.

 

버퍼 생성

- non-directallocate()wrap() 메소드를 호출하여 이용하고, directallocateDirect() 메서드를 이용한다.

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보다 큰 값을 가질 수 없다. 만약 positionlimit의 값이 같아진다면 더 이상 데이터를 쓰거나 읽을 수 없다.

limit

버퍼에서 읽거나 쓸 수 있는 위치의 한계를 나타낸다. 이 값은 capacity보다 작거나 같은 값을 가진다. 최초에 버퍼를 만들었을 때는 capacity와 같은 값을 가진다.

capacity

버퍼의 최대 데이터 개수(메모리크기)를 나타낸다. 인덱스 값이 아니라 수량임을 주의

mark

Reset() 메서드를 실행했을 때 돌아오는 위치를 지정하는 인덱스로써 mark() 메서드로 지정할 수 있다. 주의할 점은 반드시 position 이하의 값으로 지정해줘야한다. position이나 limit 값이 makr 값보다 작은 경우, mark는 자동제거된다. Mark가 없는 상태에서 reset() 메서드를 호출하면 InvalidMarkException이 발생한다.

 

- position, limit, capacity, mark 속성의 크기 관계

Markposition보다 클 수 없고, positionlimit보다 클 수 없으며, limitcapacity보다 클 수 없다.

0 <= mark <= position <= limit <= capacity

 

반응형
profile

거꾸로 바라본 세상

@란지에。

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