소프트웨어 개발/Java - Basic

ExecutorService 를 이용한 병렬처리 프로그램

늘근이 2015. 8. 10. 20:48

깔깔깔 내일은 직장에서 즐겁게 지내겠다는 마음가짐으로 병렬처리를 해본다.

아무리 어두워도 웃고다니면 절로 기분이 좋아지는법~ 깔깔깔깔깔

일단 참고는 아래의 세 사이트에서 참고했다.

http://samse.tistory.com/386

http://suein1209.tistory.com/333

http://javacan.tistory.com/124

별볼일 없으니 보지말고.


모든 놈 위에는 Executor가 있다.

엄밀히 말하면 화살표는 삼각형으로 그려야 하는데 그냥 귀찮다.

Executor 를 끌러보면 단 하나밖에 없다.


void execute(Runnable command);


그렇지만, 이를 상속받고 있는 놈인 ExecutorService는 꽤나 많은 거시기들을 가지고 있다.

 

이는 Executor의 라이프사이클을 관리하기 위해서인데, 그냥 이것저것 키고 끄고 확인하려는 작업을 위해서이다. 이는 웹서버를 작동시킬때 상당히 유용하게 쓰일수 있는데, shutdown()으로 꺼버린 후, awaitTreminated()메서드 등으로 기다리는 머시기를 구현할수 있다.

마지막으로 ScheduledExecutorService는 다음과 같은 메서드를 지니고 있다. (상속받았으니 ExecutorService가 가지고 있는놈도 당연히 있다.)

 

 

이름에 걸맞게 뭔가 스케쥴을 걸어놓고 기폭시키는 시한폭탄이 숨어져 있을것이다. 뽱!


마지막으로 Executors (복수다 복수) 클래스 (인터페이스 아니다) 안에는 Executor인터페이스에 실제 객체를 입힐수 있는 여러 유틸리티가 들어가 있다. 다음과 같이 새로운 Executor를 소환할수 있다.

 


 

이제 객체도 생성했으니, 실제로 생성된 executor객체에 넣어줄 뭔가가 있어야 한다. 영혼을 불어넣어주어야 한다. 그래야 돌아가는 목적이 생길테니까..

보통은, .Runnable 인터페이스를 구현하는데 사실 이 인터페이스는 리턴값이 없어 심심하다. 뭔가를 하고 값을 돌려받으면 더 좋지 않겠나? 사실 Runnable은 그냥 실행하는걸 태우는데 목적을 두었다. 그런데 생각해보면 다 끝나고 뭔가를 알려줄수도 있지 않겠나?

바로 여기서 멀티쓰레드 디자인패턴인 Future가 튀어나오게 된다. Future는 무엇인가? 자바에도 존재하고 스칼라에도 존재하고, 사실 처음보면 뭐가 뭔지 감이 안온다. Future는 일종의 토큰이다. 일종의 어음으로써 다 실행하고 나면 채워지는 미래를 약속한 보증수표이다. 이 디자인 패턴은 조금 복잡하므로 다른 어려운 책을 참고하면된다. 다만 번역된 책중에 마땅한게 안보인다 ㅡㅡ


자 이제, Future 객체를 생성해서 뭔가를 해보자. 일단, Callable (java.util.concurrent.Callable) 을 이용해 적당히 뭔가를 코딩한다.


class CImpl implements Callable {
	public String call() throws InterruptedException {
		Thread.sleep(5000);
		return "done";
	}
}


그리고 Future객체인 future에 executor가 가지고 있는 submit()메서드를 통해 하나의 티켓을 예약해준다. 5초가 지나면 뭔가 튀어나올것 같지 않은가? 다만, future자체를 출력해보면 객체자체의 주소가 튀어나올것이므로 future가 가지고 있는 get() 메서드를 이용해 꺼내면 된다.


		Future future = executor.submit(new CImpl());
		System.out.println(future.get());


이제 5초뒤에 done이라는 문자열을 볼수 있다.

 

done

 

보너스로 자바 1.8이상이라면 람다 형태로도 구현해볼수 있다. 귀찮은 Callable 인터페이스를 상속받는 클래스를 구현하지 않아도 된다.

		Future future = executor.submit(() -> "done");
		System.out.println(future.get());