개발하는 두더지

[Effective Java 규칙68] 스레드보다는 실행자와 태스크를 이용하라 본문

Java,Android

[Effective Java 규칙68] 스레드보다는 실행자와 태스크를 이용하라

덜지 2018. 11. 20. 15:49

[Effective Java 규칙68] 스레드보다는 실행자와 태스크를 이용하라

Effective Java 2/E 책과 구글링을 통해 내용을 정리하고 개인적인 견해가 포함된 글입니다.



작업을 순차적으로 처리하는 작업 큐가 있다고 하자. 스레드 + 큐 조합으로 만든다면 스레드에 안전하지 않게 만들어질 가능성이 높다. 이를 해결하기 위해 자바 1.5부터 java.util.concurrent 패키지에 Executor Framework라는 유연성이 높은 인터페이스 기반 태스크 실행 프레임워크라는 것이 생겼다. ExecutorService executor = Executors.newSingleThreadExecutor(); 를 만들고 실행자에 Runnable을 넘겨 실행만하면 동기화가 끝난다. executor.execute(runnable);  


큐의 작업을 처리하는 스레드를 여러개 만들고 싶을때는 스레드 풀을 만들어 사용할 수 있다. 스레드 풀에 담기는 스레드의 숫자는 고정시킬 수도있고, 가변적으로 변하게 할 수도 있다. java.util.concurrent.Executors에는 개발자가 원하는 대부분의 정적 팩터리 메서드들이 들어있다. 물론 정적 팩터리 패턴에 없는 기능을 구현하기 위해서 ThreadPoolExecutor 클래스를 이용하여 직접 스레드 풀의 동작을 세밀하게 컨트롤 할 수 있다.


어떤 Executor를 정하기 애매한 경우, 작은 프로그램이거나 부하기 크지않는 서버를 만들때는 Executors.newCachedThreadPool을 만드는 것이 좋다. 캐시 기반의 경우 작업은 큐에 들어가지 않고 실행을 담당하는 스레드로 바로 전달되기 때문이다. 하지만 가용할 스레드가 없는 경우 새 스레드를 만들고 부하가 심해지면 CPU 사용량이 100%까지 올라갈 수 있으므로 작업이 적은 시나리오에만 사용해야 한다.


부하가 심한 환경에서 사용할때는 Executors.newFixedThreadPool을 이용해서 스레드 개수가 고정된 풀을 만들거나 최대한 많은 부분을 직접 제어하기 위해 ThreadPoolExecutor 클래스를 직접 사용하는 것이 좋다. 
























Comments