본문 바로가기
개발 공부 기록하기/- Kotlin & Java

Callable과 Thread

by soulduse 2016. 2. 4.
반응형

Callable에 대한 좋은 설명이 있어서 글내용을 가져왔습니다.

출처 : http://www.codekin.com/?p=419





Callable로 무슨 처리를 어떻게 하느냐에서 시작하여 나온 케이스중 다음과 같은 케이스가 있었다.

“어떠한 서버 A와 B에게 데이터 요청을 Thread로 동시(거의 동시지만)에 요청한 다음, 응답받은 두 데이터들을 병합하는 작업 수행에 사용하면 된다.” 는 것이었다. 단, A와 B에는 날짜등과 같이 필수정렬조건이 존재하고, A나 B의 단독처리는 의미가 사라져 쓰레기 데이터가 된다.는 전재조건도 있다.

 

테스트 케이스 설정


Facebook과 Twitter의 타임라인 데이터들을 동시에 요청하여 두 타임라인데이터를 날짜별로 정렬하여 병합한다.

 

 

제한


쓰레드로 구현한다면 blocking이 되지 않아 메인 쓰레드가 start()한 후 그냥 나머지 처리를 진행하게되고 결국 두 데이터가 모두 모이지 않은 상태에서 원하지 않은 병합작업이 실행되거나, 또는 처리속도가 무지막지하게 빨라서 미쳐 양쪽의 데이터가 모두 도착하지 않았는데도 병합이 완료되었다고 하는 경우가 생길 수 있다.

이를 보완하기 위해서는 공용메모리나 파이프등을 이용하여, 하나의 쓰레드가 다른 한쪽의 처리 완료여부를 지속적으로 확인해야 한다. 물론 이러한 코드는 while() 등으로 구현될것이므로 자원낭비와 처리율저하등 심각한 문제를 야기할 수 있다.

 

 

대안 제시


 

Callable을 통하여 처리하게되면 이러한 점을 극복할 수 있다고 한다. Callable로 쓰레드 처리시 자동적으로 blocking되어 하나의 쓰레드 처리가 모두 완료될때까지 프로세스가 멈추게된다. 그러므로 모든 쓰레드 처리가 완료된 후 병합처리를 진행할 수 있을 것이다.

 

 

Thread를 통한 구현


▲ FaceBook에 요청하여 응답받는 객체 생성

 

 

▲ Twitter에 요청하여 응답받는 객체 생성

 

 

▲ 두 응답을 병합하는 객체 생성

 

 

콘솔

mergeStart
facebook response
Twitter Response

 

Callable을 통한 구현


▲ FaceBook에 요청하여 응답받는 객체 생성

 

 

▲ Twitter에 요청하여 응답받는 객체 생성

 

 

▲ 두 응답을 병합하는 객체 생성

 

 

프로세스 시작 시점의 콘솔

getFacebookTimeline… / line : 0
getTwitterTimeline… / line : 0
getTwitterTimeline… / line : 1
getTwitterTimeline… / line : 2
getFacebookTimeline… / line : 1
getTwitterTimeline… / line : 3
getTwitterTimeline… / line : 4

 

트위터의 응답이 종료된 시점의 콘솔

getTwitterTimeline… / line : 498
getTwitterTimeline… / line : 499
getFacebookTimeline… / line : 200
getFacebookTimeline… / line : 201
getFacebookTimeline… / line : 202
getFacebookTimeline… / line : 203
getFacebookTimeline… / line : 204
getFacebookTimeline… / line : 205
getFacebookTimeline… / line : 206
getFacebookTimeline… / line : 207
getFacebookTimeline… / line : 208
getFacebookTimeline… / line : 209
getFacebookTimeline… / line : 210

 

페이스북의 응답이 종료된 시점의 콘솔

getFacebookTimeline… / line : 299
Facebook Response is Done!
Twitter Response is Done!
Merge Start!
Twitter timeline : 0
Twitter timeline : 1
Twitter timeline : 2

 

 

Callable을 통한 구현 설명


Thread와는 달리 Callable은 각각 쓰레드가 생성되어 두 요청에 대한 데이터들을 각각 인풋하는데 중요한점은 메인 클래스에서 facebook 보다 뒤에 처리되는 twitter의 요청이 완료되어도 앞에 있는 facebook의 요청이 완료되지 않으면 진행하지 않는다는 점이다. 정확히는 facebook의 응답 값을 get하지 못하였기 때문에 해당 라인에서 블락킹 된 것이다.

여기서 알아 두어야 할 것은 Future클래스에 대한 것으로, 이 클래스를 통하여 Callable이 반환한 값을 취할 수 있다. 다른 말로 하자면 Callable이 어떤 값을 반환할때까지 이 클래스는 get()할 수 없다(블락킹 된다)는 것이다. 좀 혼동이 올 수 있으니 다음과 같이 생각하면 쉽게(뭐?) 이해할 수 있을 것이다.

Future클래스의 get()메서드는 해당 인스턴스가 바라보고 있는 Callable인스턴스가 처리를 마치고 값을 반환하기 전까지 Future.get()을 실행한 라인에서 블락킹 된다.

그래도 Future클래스의 이름(특성)이 이해하기 어렵다면 또 이렇게 생각하면 쉽다.(뭐??)

“Future클래스는 Callable을 통해 반환’될’ 값을 get 할 수 있다.”

즉, 어떤 메서드인지간에 신경쓰지말고 하여간 그 메서드가 주구장창 돌아가다가 값을 반환하는 그때 get할 수 있다는 이야기이다.(뭐 이래 풀어쓰기가 어려워) 따라서, 주구장창 돌아가다가 값이 반환되는 미래의 어느 시점이라는 그 죽일놈을 기다리게 블락킹 한다는 소리가 된다.

 

 

Console 메시지 설명


위 콘솔에서 프로세스가 시작되고 Facebook과 Twitter가 서로 응답을 받아 병합처리하고 있다.

콘솔에서는 계속해서 facebook 응답과 twitter응답을 받아내고 있고, 메인쓰레드는 지금 facebook응답을 가져오는 callable을 바라보고 있는 Future의 get()메서드(아 겁나 길어)를 만난상태이고 여기서 블락킹이 되어있는 상태이다.

이후에 Facebook 응답이 종료되고 get()의 블락킹이 풀리게 되고, Twitter 응답을 받는 또 다른 Callable이 반환을 마치지 않았으므로 그 다음 get()에서 메인 쓰레드는 다시 블락킹이 된다.

Twitter의 응답이 종료되고 메인 쓰레드의 블락킹이 풀리게 되어 MergeStart를 콘솔에 출력하고 병합을 시작한다.


반응형