ThreadPoolExecutor - 1

"일반 프로그래머는 때때로 수행해야 하는 작은 작업이 많다는 사실을 조만간 깨닫게 됩니다."

"게임을 작성하고 있다면 개별 캐릭터가 수행하는 작업입니다."

"웹 서버를 작성하는 경우 사진을 업로드하고, 원하는 형식으로 코드 변환하고, 원하는 템플릿을 적용하는 등 사용자로부터 들어오는 다른 명령입니다."

"조만간 모든 큰 작업은 작고 관리 가능한 일련의 작업으로 나뉩니다."

"따라서 이러한 맥락에서 미묘한 질문이 생깁니다. 이 모든 작업을 어떻게 관리해야 할까요? 1분에 수백 개의 작업을 수행해야 한다면 어떻게 해야 할까요? 각 작업에 대한 스레드를 생성하는 것은 별 의미가 없습니다. Java 머신은 각 스레드에 꽤 많은 리소스를 할당합니다."

"즉, 스레드를 만들고 파괴하는 데 작업 자체보다 더 많은 시간과 리소스가 필요할 수 있습니다."

"Java의 제작자는 이 문제에 대한 우아한 솔루션인 ThreadPoolExecutor를 내놓았습니다 .

" ThreadPoolExecutor 는 내부에 두 가지가 있는 클래스입니다."

A)  프로그램에서 발생하는 작업을 추가할 수 있는 작업 대기열.

B) 이러한 작업을 수행하는 스레드 그룹인 스레드 풀.

"게다가 스레드는 작업이 완료되면 파괴되지 않습니다. 대신 새 작업이 나타나자마자 시작할 준비를 하기 위해 잠이 듭니다."

" ThreadPoolExecutor 를 생성할 때 생성할 최대 스레드 수와 대기할 수 있는 최대 작업 수를 설정할 수 있습니다. 즉, 스레드 수를 예를 들어 10개로 제한할 수 있으며 대기 중인 작업이 100개입니다."

"이것은 ThreadPoolExecutor가 작동하는 방식입니다."

1)  새 작업을 추가하면 대기열 끝에 배치됩니다.

2)  큐가 가득 차면 예외가 발생합니다.

3)  작업을 완료하면 각 스레드는 대기열에서 다음 작업을 가져와 실행을 시작합니다.

4) 대기열에 작업이 없으면 새 작업이 추가될 때까지 스레드가 휴면 상태가 됩니다.

"작업자 스레드 수를 제한하는 접근 방식은 스레드가 많을수록 서로 간섭이 심하다는 점에서 유리합니다. 5-10개의 작업자 스레드와 긴 작업 대기열을 갖는 것이 훨씬 더 효과적입니다. 메모리, 프로세서 시간, 데이터베이스 액세스 등 리소스를 놓고 서로 경쟁할 작업 급증에 대해 100개의 스레드를 생성합니다."

"작동 중인 ThreadPoolExecutor 의 예는 다음과 같습니다 ."

ExecutorService service = Executors.newFixedThreadPool(2);

for(int i = 0; i < 10; i++)
{
 service.submit(new Runnable() {
    public void run()
    {
     // Here we download something big from the Internet.
    }
 });
}

"어, 안 보여…"

" newFixedThreadPool 메서드가 호출될 때 ThreadPoolExecutor 개체가 생성됩니다."

따라서 사용하기가 매우 쉽습니다. 제출 방법으로 작업을 추가하자마자 다음을 수행합니다.

A)  작업을 실행하기 위해 잠자는 스레드가 있으면 깨웁니다.

B)  대기 중인 스레드가 없으면 작업에 대한 새 스레드를 만듭니다.

C)  최대 스레드 수에 도달하면 작업을 대기열 끝에 넣습니다.

"예제에 의도적으로 «인터넷에서 큰 항목을 다운로드합니다»를 포함시켰습니다. «인터넷에서 큰 항목 다운로드» 작업이 100개 있는 경우 동시에 많은 작업을 실행하는 것은 의미가 없습니다. 인터넷 연결의 대역폭 제한에 의해 억제될 것입니다. 이 경우 두 개의 스레드로 충분해야 합니다. 위의 예에서 볼 수 있는 내용입니다."

ExecutorService service = Executors.newFixedThreadPool(2);

"많은 작업을 수행하는 것이 그리 어렵지 않은 것으로 나타났습니다."

"예. 상상 이상으로 쉽습니다. 하지만 김이 알려줄 것입니다."