본문 바로가기
JAVA

ExecutorService / ThreadPoolExecutor

by 아이티.파머 2018. 11. 12.
반응형

Mulity Thread

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

threadPoolExecutor 인자

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

  • corePoolSize : 최소 pool size
  • maximumPoolSize : 최대 pool size
  • keepAliveTime
  • TimeUnit
  • BlockingQueue : 사용할 Queue 종류

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));

 

오라클 문서에 권장된 종료 방법 참고

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

[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 pdocs.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' 카테고리의 다른 글

java Blocking Queue  (0) 2019.02.26
JAVA Exception 정리  (0) 2019.02.26
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