IO 장치들은 여러 문제가 있음.

  • 다양한 주변 장치가 존재
    • 서로 다른 포멧의 데이터를 전송
    • 서로 다른 속도로 동작
  • CPU 와 RAM 보다 I/O 작업이 느림
  • 입출력 모듈을 필요로 한다.

여기서 입출력 모듈이란 CPU 와 메모리의 인터페이스이고 하나 또는 그 이상의 주변 장치에 대한 인터페이스를 의미

 

Programmed I/O (프로그램 입출력)


입출력 모듈 중에 프로그램 입출력은 IO 로 부터 제어권을 CPU 가 가져와서 작업을 진행하는 것으로 CPU 는 입출력 모듈이 명령어의 수행을 완료할 때까지 기다립니다. 따라서 이 방식은 CPU 의 시간을 소모합니다.

Java I/O 는 이런 문제점 때문에 파일 입출력이 느리다는 인상을 많이 주었음. 이런 문제점을 Non-blocking IO(nio, New IO) API를 제공해서 극복해왔습니다.

 

Blocking, Non-Blocking


https://way-be-developer.tistory.com/295

 

Synch/Async vs blocking/non-blocking 차이

동기/비동기, blocking/non-blocking 의 차이는 동기/비동기, blocking/non-blocking 두 그룹의 차이는 관심사가 다르다. blocking/non-blocking 호출되는 함수가 바로 return 하느냐 마느냐가 관심사이다. 호출된..

way-be-developer.tistory.com

위에 북마크를 참고하면 Blocking, Non-Blocking 에 대한 개념을 잡을 수 있습니다.

NodeJS 의 장점은 이벤트 기반의 비동기 논블로킹 IO 지원으로 자원을 효율적으로 사용한다는 장점이 있다.

 

Blocking API


Blocking API 란 API 를 호출한 Thread 가 API 의 작업이 끝날 때까지 다른 동작을 하지 않는 API 를 블로킹이라고 한다.

Java의 기본 IO 관련 API 들이 Blocking 방식을 사용하는데 InputStream, OutputStream이 있다.

 

InputStream inputstream = new FileInputStream("c:\\\\data\\\\input-text.txt");

int data = inputstream.read(); // Blocking!
while(data != -1) {
  doSomethingWithData(data);
  data = inputstream.read();
}
inputstream.close();

위 코드는 Blocking API 들은 반환값을 받을 때까지 Blocking 되어서 Thread 는 idle (프로세스를 실행하고 있지 않은 상태)로 유지됩니다. 예시는 파일이지만 네트워킹 처럼 오래걸리는 작업의 경우 Blocking 으로 작업을 수행하면 bottle neck(병목) 의 원인이 되기 쉽습니다.

 

Non Blocking API


Non-Blocking API 는 쉽게 말해서 API 호출시 요청한 작업의 완료 여부와 상관 없이 즉각적으로 현재 상태에 대한 응답이 옵니다. 그래서 API 호출 후 Thread 제어권이 있기 때문에 다른 작업을 진행할 수 있음

Java NIO (New IO) 의 등장으로 Non Blocking방식을 구현할 수 있게 되었습니다.

하나의 Thread 가 IO작업에 의존적이지 않기 때문에 하나의 Thread 로 다수의 IO를 처리할 수도 있습니다.

 

NIO 와 IO 의 주요 차이점


NIO 와 IO는 개념적으로는 Blocking, Non-Blocking 의 차이가 있지만, 그 외에도 차이점이 존재합니다.

  • Stream Oriented vs Buffer Oriented
  • Blocking IO vs Non Blocking IO
  • Selector

 

Stream 기반 vs Buffer 기반


Java NIO 와 IO 사이의 큰 차이는 IO는 Stream 기반이고, NIO는 Buffer 기반이라는 점입니다.

즉, 스트림 기반의 Java IO는 스트림으로 부터 한번에 여러 바이트를 읽습니다. 읽은 바이트를 가지고 무엇을 할지는 사용하는 이에게 달려있고, 데이터는 어디에도 캐시되지 않습니다.

그리고 스트림 속 데이터에서 앞 뒤로 이동할 수도 없습니다. 만약 스트림으로 부터 읽은 데이터 내부에서 앞 뒤로 이동할 필요가 있다면 버퍼를 만들어 캐싱해야 합니다.

버퍼 기반의 Java NIO는 조금 다릅니다. 이미 처리된 buffer 로 부터 데이터를 읽어서 필요하다면 버퍼 내부에서 앞뒤로 이동할 수 있습니다. 이는 데이터를 처리하는 동안 좀 더 유연함을 제공합니다.

 

Blocking vs Non-Blocking IO


Java IO의 여러 스트림들은 Blocking 방식입니다. 하나의 Thread가 read() or write()를 발생 시킬 때, 해당 thread는 데이터를 읽을 때까지 혹은 데이터를 적을 때까지 blocked 상태입니다.

Java NIO의 Non-Blocking mode 는 thread 가 채널을 통해서 데이터를 읽는 것을 요청한 뒤, 이용 가능한 데이터만을 얻을 수도 있고, 만약 아무 데이터가 없다면 즉시 리턴하여 thread 가 동작할 수 있게 합니다. (스레드가 Blocking 되지않습니다.)

Non-Blocking writing 도 마찬가지로 thread 는 channel 을 통해서 어떤 데이터를 쓰도록 요청하고 데이터를 전부 다 작성할 동안 기다리지 않고 그 동안 다른 동작을 할 수 있습니다.

Non-Blocking thread이 block 되지 않는 순간엔 다른 채널에 IO를 수행할 수도 있습니다.

따라서 단 하나의 thread 가 다수의 input, output channels 를 관리 할 수도 있습니다.

 

Selector


Java NIO Selector는 하나의 thread 가 여러개의 input channel 들을 모니터링 할 수 있습니다.

이런 특징은 다수의 Thread 로 IO를 관리하는 방식에 비해 Thread Switching 을 줄이기 때문에 이점을 줍니다.

하나의 selector 를 사용해서 다수의 channels 를 등록할 수 있으며 하나의 스레드를 사용해서 input 을 처리할 수 있는 channel 을 선택할 수 있으며 또한 writing 을 위해 준비된 channel 을 선택할 수 있다.

이런 매커니즘은 하나의 thread 가 여러개의 channel을 관리하기 쉽게 해준다.

이제 Java I/O 패키지에 대해서 좀 더 자세하게 알아보려고 한다.

 

Java I/O 패키지란?


💡 Provides for system input and output through data streams, serialization and the file system. Unless otherwise noted, passing a null argument to a constructor or method in any class or interface in this package will cause a NullPointerException to be thrown.

쉽게 말하면 데이터 스트림, 직렬화 및 파일 시스템을 통한 시스템 입력 및 출력을 제공. 즉 Java I/O 패키지 않에는 파일 파일 입출력과 관련된 클래스을 포함하고 있다는 의미이다.

 

바이트 단위 스트림


  • InputStream, OutputStream 둘다 바이트 기반 입출력. 스트림의 최상위 클래스로 추상 클래스이다.
  • 관련된 모든 바이트 기반 입출력 스트림은 이 클래스를 상속 받아서 만들어졌다.
  • 그림, 멀티미디어, 문자 등 모든 종류의 데이터를 주고 받을 수가 있다.
  • Java I/O 도식표

Java.io 패키지의 주요 클래스 설명

File 파일 시스템의 파일 정보를 얻기 위한 클래스
Console 콘솔로부터 문자를 입출력하기 위한 클래스
InputStream / OutputStream 바이트 단위 입출력을 위한 최상위 입출력 스트림 클래스
FileInputStream / FileOutputStream 바이트 단위 입출력을 위한 하위 스트림 클래스
DataInputStream / DataOutputStream 바이트 단위 입출력을 위한 하위 스트림 클래스
ObjectInputStream / ObjectOutputStream 바이트 단위 입출력을 위한 하위 스트림 클래스
PrintStream 바이트 단위 입출력을 위한 하위 스트림 클래스
BufferedInputStream / BufferedOutputStream 바이트 단위 입출력을 위한 하위 스트림 클래스
Reader / Writer 문자 단위 입출력을 위한 최상위 입출력 스트림 클래스
FileReader / FileWriter 문자 단위 입출력을 위한 하위 스트림 클래스
InputStreamReader / InputStreamWriter 문자 단위 입출력을 위한 하위 스트림 클래스
PrintWriter 문자 단위 입출력을 위한 하위 스트림 클래스
BufferedReader / BufferedWriter 문자 단위 입출력을 위한 하위 스트림 클래스

 

문자 단위 스트림


  • Reader, Writer 둘다 문자 데이터 기반 입출력의 최상위 클래스이다. 관련된 모든 텍스트 기반 입출력은 이 클래스를 상속 받아서 만들어진다.
  • 문자데이터를 입출력할 때 사용하는 문자 기반의 스트림이다.
  • 오로지 문자 데이터를 주고 받기 위해서 특화되어 있다.

 

보조 스트림


  • 스트림의 기능을 보완하기 위해서 나온 스트림이다. (입출력 성능 속도 향상, 데이터 포멧 지원 등)
    1. 실제 데이터를 주고 받지 않는다.
    2. 데이터를 주고 받을 수 없기 때문에 스트림을 생성해서 등록한 뒤에 사용해야 한다.
    DataInputStream dataInputStream = new DataInputStream(new FileInputStream("test.txt"))
    

 

실험


코드를 공개하고 싶긴하지만, 다른 사람이 작성한 코드이기 때문에 정확한 코드를 게시하진 않고 결과만 말씀 드리겠습니다. 코드는 아래 블로그에 들어가 직접 보시면 될 것 같습니다.

 

[FileReader로 47.2MB 파일을 읽을 경우] vs [BufferReader로 47.2MB 파일을 읽을 경우]

전자는 3분이 넘어도 빌드하지 못했다고 한다. 후자는 24초만에 빌드를 성공했다고 한다.

 

 

 

참고

https://blackinkgj.github.io/IO/

 

[컴퓨터 구조] Input/Output

입출력에 관해서 알아보도록 한다.

blackinkgj.github.io

https://velog.io/@jihoson94/BIO-vs-NIO

 

Java IO vs NIO

Basic IO와 New IO에 대해 알아보겠습니다. 차이점과 장단점을 비교하면 진행해보겠습니다.Referencehttp://tutorials.jenkov.com/java-nio/nio-vs-io.html비교할 요소는 아래 3가지입니다.Stream Orient

velog.io

https://velog.io/@ljs0429777/Java-IO

 

Java I/O

Input과 Output의 약자로 입출력을 의미함입출력의 간단한 예로 키보드로 텍스트를 입력하고, 모니터로 입력한 텍스트를 출력하는 것임Input -> Output (지극히 개인적인 비유법,,)👆 식에서 "->" 스트

velog.io