ExecutorService / ThreadPoolExecutor

2018.11.12 21:05JAVA

동시 작업을 하기 위한 방법으로 1.5 에서 제공하는 ExecutorService 를 사용한다.
예전엔 Thread를 관리하기 위해 ThreadGroup을 만들고 관리 하는 방법이 복잡하고 어려운점이 있었다.
ExecutorService를 이용하면 내부적으로 ThreadPoolExecutor 를 생성한다. (new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());)

 

ThreadPoolExecutor 인자 
ThreadPoolExecutor(corePoolSize, maximumPoolSize ,keepAliveTime, TimeUnit, BlockingQueue)

 

Executor 프레임웍 특징

  • 쓰레드 풀을 사용

  • 무거운 쓰레드는 미리 할당 가능

  • 태스크와 쓰레드를 생성하고 관리하는 것을 분리

  • 쓰레드 풀안의 쓰레드는 한번해 하나씩 여러 태스크를 실행

  • 태스크 큐를 이용해 태스크를 관리

  • Executor Service를 더이상 필요 없으면 중지

  • Executor Service가 멈추면 모든 쓰레드도 중지

 

ExecutorService 기본 Method 정보 및 사용법

기본 생성자 특징

newFixedThreadPool  
지정된 숫자 만큼으 Thread를 생성하여 순차 적으로 실행 한다.   

new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());  

newSingleThreadExecutor   
하나의 작업이 완료된뒤에 순차적으로 다음 작업이 실행된다.    

(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue()))  


CachedThreadPool 사용  
CachedThreadPool은 FixedThreadPool과 달리 태스크의 숫자에 따라 쓰레드의 숫자가 가변된다는 것이다. 그러므로 생성시 쓰레드 숫자를 지정할 필요가 없다.  
ThreadPoolExecutor(0, Integer.MAX\_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue())  

 

ExecutorService Example

// 동시에 4개 실행   
ExecutorService executorService = Executors.newFixedThreadPool(4);  

.newFixedThreadPool 시에 new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());   
과 같이 ThreadPoolExecutor을 생성한다.  개발 성격에 따라 맞는 성향의 Queue를 생성 할 수 있다.   



// 이미 시작된 Task는 실행 하고, 새로운 작업은 받지 않음  
executorService.shutdown()   

// 작업이 완료되었는지 확인 , 작업이 완료된후 true   
executorService.isTerminated()    

// executorService.shutdown() 셧다운 요청이  있은 후에 true로 변경 된다.  
executorService.isShutdown()      

// 지정된 시간 동안대기 하며 모든 작업이 모든 중지되었는지 체크 한다.   
executorService.awaitTermination(10, TimeUnit.SECONDS)   

지정된 10초동안 대기 하며 모든 작업이 모든 중지되었는지 체크 한다. 작업이 모두 중지 될때 까지, 지정된 시간별로 Loop 실행   
while(!executorService.awaitTermination(10, TimeUnit.SECONDS))  

 

 

Task 종료 방법

1. 특정 시간 단위로 작업이 끝날때 까지 종료 체크 , 특정 시간이 지나면 강제 종료 

executorService.shutdown() 

do {

	System.out.println("Running.... {}" + executorService.isTerminated());
	// 작업이 완료되었으면 즉시 정지 한다. 
	if (executorService.isTerminated()) {
		System.out.println("Running....2 {}" + executorService.isTerminated());
		executorService.shutdownNow();
	}

	// 지정된 시간 별로(10초단위) 작업이 모든 작업이 중지되었는지 체크
	// 작업이 완료되었으면 루프 해제 
} while (!executorService.awaitTermination(10, TimeUnit.SECONDS));

 

 

2. 특정 시간 단위로 작업이 끝날때 까지 종료 체크하며, 작업이 끝날때 까지 대기 

do {
	try {

      // 종료 요청이 있었는지 체크 
      if(!executorService.isShutdown()) {

          System.out.println("종료 요청");
          // 이미 시작된 Task는 실행 하고, 새로운 작업은 받지 않음
          executorService.shutdown();
      }
	} catch (Exception e ) {
    	// 오류로 모든 Task 강제 종료
    	executorService.shutdownNow();
        
        // TODO 로그 남길것
   }

 // 지정된 시간 별로(10초단위) 작업이 모든 작업이 중지되었는지 체크
 // 작업이 완료되었으면 루프 해제 
} while (!executorService.awaitTermination(2, TimeUnit.SECONDS));

 

3. 오라클 문서에 권장된 종료 방법 

https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html

 

ExecutorService (Java Platform SE 8 )

An Executor that provides methods to manage termination and methods that can produce a Future for tracking progress of one or more asynchronous tasks. An ExecutorService can be shut down, which will cause it to reject new tasks. Two different methods are p

docs.oracle.com

	void shutdownAndAwaitTermination(ExecutorService pool) {
	   pool.shutdown(); // Disable new tasks from being submitted
	   try {
	     // Wait a while for existing tasks to terminate
	     if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
	       pool.shutdownNow(); // Cancel currently executing tasks
	       // Wait a while for tasks to respond to being cancelled
	       if (!pool.awaitTermination(60, TimeUnit.SECONDS))
	           System.err.println("Pool did not terminate");
	     }
	   } catch (InterruptedException ie) {
	     // (Re-)Cancel if current thread also interrupted
	     pool.shutdownNow();
	     // Preserve interrupt status
	     Thread.currentThread().interrupt();
	   }
	 }

'JAVA' 카테고리의 다른 글

blockingqueue method  (0) 2019.02.26
JAVA Exception 정리  (0) 2019.02.26
ExecutorService / ThreadPoolExecutor  (0) 2018.11.12
JSR303 HV000030 Error  (0) 2016.10.19
ExecutorService 를 이용한 javaMail 대량 메일 발송 bulk mail send  (0) 2016.10.04
JAVA try catch with resource  (0) 2016.03.15