이전에 닷넷 섹션에서 쓰레드 분배전략에 대해 설명을 드린적이 있습니다.

(참고) http://nonstop.pe.kr/dotnet/11920


자바에서도 비슷한 방법으로 작업 분배전략을 세울수 있습니다.. 


예전에는 작업량에 따라 미리 설정된 스레드 갯수만큼 작업을 나눠 Thread 클래스에 작업을 할당하는 전통적인 방법을 많이 사용했었습니다.

그러나, Java5에서는 향상된 Thread Pooling 방법이 추가되었습니다.


ThreadPool 관리의 ExecutorService, Callable 객체입니다.

ExcutorService에 전달할 객체는 Runable이나, Callable을 구현해 전달할 수 있습니다.

Runable로 구현된 객체는 return타입이 void이므로 값을 리턴받을 수 없기때문에 사용에 제약이 따릅니다.

그래서..Callable 구현객체를 사용하고, 그에 대한 결과는 Future를 통해 값을 가져올 수 있게됩니다.


package com.test;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class MyCallable implements Callable<String> {

	@Override
	public String call() throws Exception {
		Thread.sleep(1000);
		//return the thread name executing this callable task
		return Thread.currentThread().getName();
	}

	public static void main(String args[]){
		//Get ExecutorService from Executors utility class, thread pool size is 5
		ExecutorService executor = Executors.newFixedThreadPool(5);
		//create a list to hold the Future object associated with Callable
		List<Future<String>> list = new ArrayList<Future<String>>();
		//Create MyCallable instance
		Callable<String> callable = new MyCallable();
		for(int i=0; i< 100; i++){
			//submit Callable tasks to be executed by thread pool
			Future<String> future = executor.submit(callable);
			//add Future to the list, we can get return value using Future
			list.add(future);
		}
		for(Future<String> fut : list){
			try {
				//print the return value of Future, notice the output delay in console
				// because Future.get() waits for task to get completed
				System.out.println(new Date()+ "::"+fut.get());
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			}
		}
		//shut down the executor service now
		executor.shutdown();

		System.out.println("-----finish-----");
	}

}


 결과)

Thu Jan 15 22:19:47 KST 2015::pool-1-thread-1
Thu Jan 15 22:19:48 KST 2015::pool-1-thread-2
Thu Jan 15 22:19:48 KST 2015::pool-1-thread-3
Thu Jan 15 22:19:48 KST 2015::pool-1-thread-4
Thu Jan 15 22:19:48 KST 2015::pool-1-thread-5
Thu Jan 15 22:19:48 KST 2015::pool-1-thread-1
Thu Jan 15 22:19:49 KST 2015::pool-1-thread-4
Thu Jan 15 22:19:49 KST 2015::pool-1-thread-5
Thu Jan 15 22:19:49 KST 2015::pool-1-thread-2
Thu Jan 15 22:19:49 KST 2015::pool-1-thread-3

<생략>


결과를 보시면, 쓰레드가 순차적으로 할당되어 수행되고 쓰레드풀에 할당된 수만큼만 생성하고, 그 이후부터는 먼저끝난놈이 다음작업을 받아 수행하게 됩니다.


우리는 Thread Pooling 아키텍처에 고민할 필요없이 사용하면 될것이고, 구현하고자 하는 비즈니스로직에 집중하면 됩니다.


추가적으로 ThreadPoolExecutor, ScheduledThreadPoolExecutor 클래스를 이용하면, 다양한 고급기능을 사용할 수 있습니다.


출처) http://www.journaldev.com/1090/java-callable-future-example

참고) http://www.javacodegeeks.com/2013/01/java-thread-pool-example-using-executors-and-threadpoolexecutor.html

참고) http://powerkkim.tistory.com/entry/ThreadPoolExecutor-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0