이 글은 원 저자 Jakob Jenkov의 허가로 포스팅된 번역물이다.

원문 URL : http://tutorials.jenkov.com/java-concurrency/benefits.html



멀티쓰레딩이 그 위험요소에도 불구하고 여전히 사용되는 이유는 얻을 수 있는 장점이 있기 때문이다. 그 중 몇가지는 다음과 같다.

  • 향상된 자원 활용성
  • 상황에 따른 더 간단한 프로그램 디자인
  • 프로그램의 반응성 향상

향상된 자원 활용성


로컬 파일 시스템의 파일을 읽고 처리하는 어플리케이션을 생각해보자. 디스크에서 파일을 읽는 데에 5초가 소요되고, 이를 처리하는 데에는 2초가 소요된다. 2개의 파일을 가공한다면 다음과 같은 시간이 소요된다.


  5 seconds reading file A
  2 seconds processing file A
  5 seconds reading file B
  2 seconds processing file B
-----------------------
 14 seconds total


읽기 작업에서는, 디스크가 데이터를 읽는 것을 기다리는 데에 CPU의 시간 대부분을 소모한다. 이 시간동안 CPU는 일하지 않는다. 이건 다른 것이 될 수 있다. 작업의 순서를 바꾼다면, CPU의 효율성은 더 나아질 수 있다.


  5 seconds reading file A
  5 seconds reading file B + 2 seconds processing file A
  2 seconds processing file B
-----------------------
 12 seconds total


CPU는 첫 번째 파일이 읽혀지길 기다린다음 두 번째 파일을 읽기 시작한다. 두 번쨰 파일이 읽혀지는 동안, CPU 프로세스들은 첫 번째 파일을 처리한다. 여기서, 디스크에서 파일이 읽히는 동안 CPU는 거의 놀고 있다는 점을 기억하라.

보통의 경우, CPU는 입출력을 기다리는 동안 다른 작업을 할 수 있는데, 이건 디스크 입출력 뿐만 아니라 네트워크 입출력 혹은 사용자의 입력의 경우도 마찬가지이다. 네트워크와 디스크 입출력은 CPU와 메모리 입출력보다 상당히 느리다.


상황에 따른 더 간단한 프로그램 디자인


 당신이 싱글쓰레드 어플리케이션에서 위와 같은 작업 순서로 읽기와 처리 작업을 직접 한다면, 각 파일에 대한 읽기/처리 작업 상태를 계속 파악하고 있어야 할 것이다. 한 파일에 대한 읽기/쓰기 작업을 두 개의 쓰레드에게 각각 맡긴다면, 이 쓰레드들은 디스크가 파일을 읽어올 때까지 블록 상태에 놓일 것이다. 이 디스크의 작업을 기다리는 동안, 다른 쓰레드들은 파일의 이미 읽혀진 부분들에 대한 처리 작업을 위해 CPU를 사용할 수 있다. 이 과정은 디스크가 파일을 읽어 메모리에 적재하기 위해 계속해서 가동되는(kept busy at all times) 결과를 낳는다. 이건 디스크과 CPU 모두에게 더 효율적인 운용 방법이 된다. 각 쓰레드는 한 파일에만 집중할 수 있기에, 이는 또한 프로그램에게도 더 쉬운 것이다.



프로그램의 반응성 향상


 싱글쓰레드를 멀티쓰레드로 바꾸는 또다른 목적은 어플리케이션의 더 나은 반응성을 위해서이다(to achieve a more responsive). 몇 포트로 사용자의 요청을 받는 서버 어플리케이션을 생각해보자. 하나의 요청이 오면 어플리케이션은 이를 처리하고 대기 상태로 돌아간다(listening). 이런 서버의 동작은 다음과 같다.


 
  while(server is active){
    listen for request
    process request
  }


한 요청이 처리되는 데에 긴 시간이 소요되면, 그동안 다른 새로운 클라이언트의 요청을 받을 수가 없다. 서버가 요청 대기상태여야만 클라이언트의 요청은 처리될 수 있다.

이를 대체할 수 있는 디자인은 요청 대기 쓰레드가 워커 쓰레드에게 요청을 맡기고 자신은 즉각 대기 상태로 돌아가는 형태가 될 수 있다. 워커 쓰레드는 요청을 처리하고 클라이언트에게 결과를 전송한다. 이 디자인은 다음과 같다.


  while(server is active){
    listen for request
    hand request to worker thread
  }


이 디자인에서 서버 쓰레드는 더 빠르게 대기 상태로 회귀할 것이고, 클라이언트들은 서버에게 요청을 보낼 수 있다. 서버의 반응성이 향상된 것이다.

데스크톱 어플리케이션의 경우도 같다. 당신의 클릭 버튼이 긴 작업 시간을 요구한다면, 그리고 이 작업의 쓰레드가 윈도우나 버튼을 업데이트하는 쓰레드라면, 어플리케이션은 이 작업 동안 반응할 수 없는 상태에 될 것이다. 여기서 이 작업이 워커 쓰레드로 전달된다면 워커 쓰레드가 작업을 처리하는 동안 윈도우 쓰레드는 유저의 요청을 받을 수 있다. 워커 쓰레드가 작업을 마치면 윈도우 쓰레드에게 신호를 보낸다. 윈도우 쓰레드는 어플리케이션 윈도우에 작업 결과를 업데이트한다. 워커 쓰레드가 존재하는 프로그램 디자인의 반응성은 보다 향상될 것이다.



'Java > Concurrency' 카테고리의 다른 글

자바 쓰레드 시작하기  (0) 2017.04.09
컨커런시 vs. 페러럴리즘  (0) 2017.04.09
컨커런시 모델  (0) 2017.04.09
멀티쓰레딩의 단점  (0) 2017.04.09
자바 컨커런시 / 멀티쓰레딩 튜토리얼  (0) 2017.04.09

+ Recent posts