안드로이드/Thread2014.01.17 02:13

항상 ThreadPool에 대해 관심은 있었으나 

뭔가 복잡할거 같고 어렵고 접근하기 힘들어 그냥 Thread로만 대충 사용하다 보니 Multi Thread 환경에서 대략 난감인 경우들이 좀 있다.

그래서 찾아 보니 .ThreadPoolExecutor 라는 놈을 발견하게 되었다.


이것의 사용법을 함 알아보자.

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, 
BlockingQueue <Runnable > workQueue)

corePoolSize : 실행할 최소 Thread수.

maximumPoolSize : 최대 Thread 지원수

keepAliveTime : 현재 풀에 corePoolSize 의 수보다 많은 thread가 있는 경우, 초과한 만큼의 thread는, IDLE 상태가 되어 있는 기간이 keepAliveTime 를 넘으면(자) 종료합니다 

unit : 시간단위.

- workQueue : 처리 큐.

( Java Doc 참고 : http://xrath.com/javase/ko/6/docs/ko/api/java/util/concurrent/ThreadPoolExecutor.html )


여기서 중요한것은 큐입니다.

JavaDoc을 보면.BlockingQueue 에 적용가능한 Queue는 다음과 같습니다.


● SynchronousQueue : 

 워크 큐에 적절한 디폴트의 선택사항은, 태스크를 보관 유지하지 않고 thread에 핸드 오프.

일반적으로 직접 핸드 오프에서는, 송신된 새로운 태스크가 거부되는 것을 회피하기 위해서, 안 바운드 형식의 maximumPoolSizes 가 필요합니다.

이것에 의해, 평균해 처리 능력을 넘는 속도로 커멘드가 차례차례로 도착하면(자), 안 바운드 형식의 thread가 커질 가능성이 있습니다.

 LinkedBlockingQueue :

 -  corePoolSize 의 모든 thread가 Busy 상태인 경우에, 새로운 태스크는 큐내에서 대기합니다. 이것에 의해, corePoolSize 를 넘는 thread는 작성되지 않게 됩니다. 즉 maximumPoolSize 의 값은 효과가 없어집니다. (maximumPoolSize 값은 의미 없음)

각 태스크가 완전하게 독립하고 있기 (위해)때문에, 태스크가 상호의 실행에 영향을 주지 않는 경우는 이 방식이 적절하다라고 하는 것이 있습니다 (Web 페이지 서버의 경우 등).

이 방식의 큐잉은, 일시적으로 급증한 요구를 처리하는 경우 등은 편리합니다만, 평균해 처리 능력을 넘는 속도로 커멘드가 차례차례로 도착하면(자), 안 바운드 형식의 워크 큐가 커질 가능성이 있습니다.

● ArrayBlockingQueue : 

 한정된 maximumPoolSizes 로 사용하면(자) 자원 부족을 회피할 수 있습니다만, 조정과 제어가 어려워질 가능성이 있습니다. 큐 사이즈와 최대 풀 사이즈는 서로 트레이드 오프의 관계가 되는 일이 있습니다. 


-----------------------------------------------------------------------------------------

가장 기본적인 사용

LinkedBlockingQueue 를 사용 ]

- 2개의 Thread사용

- 최대 4개 Thread사용 (LinkedBlockingQueue에서는  maximumPoolSize 값은 의미 없음 )

- 60초의 Timeout 설정

- 큐는 LinkedBlockingQueue 

ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 2, 4, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()  );

        

        for( int i = 0; i < 6; i++ )

        {

            threadPool.execute( new Runnable()

            {

                public void run()

                {

                    System.out.println( "Thread " + Thread.currentThread().getName() + " Start" );

                    

                    try{ Thread.sleep( 1000 ); } catch( Exception e ) {} 

                    

                    System.out.println( "Thread " + Thread.currentThread().getName() + " End" );

                }

            } );

        }

- 이렇게 하면 총 6개의 Thread가 돌지만. 2개의 Thread가 실행되고 나머지는 큐에 대기하고 있다가 2개의 Thread가 종료되면 이후 실행된다.


[ 실행 결과 ]

Thread pool-1-thread-1 Start  

Thread pool-1-thread-2 Start

Thread pool-1-thread-1 End

Thread pool-1-thread-1 Start

Thread pool-1-thread-2 End

Thread pool-1-thread-2 Start

Thread pool-1-thread-1 End

Thread pool-1-thread-1 Start

Thread pool-1-thread-2 End

Thread pool-1-thread-2 Start

Thread pool-1-thread-1 End

Thread pool-1-thread-2 End




[ SynchronousQueue  사용 ] 

- 2개의 Thread사용

- 최대 4개 Thread사용  ( SynchronousQueue 사용시에는 maximumPoolSizes(최대 Thread개수) 값이 필요)

- 60초의 Timeout 설정

- 큐는 SynchronousQueue  

ThreadPoolExecutor threadPool = new ThreadPoolExecutor( 2, 4, 60, TimeUnit.SECONDS, new SynchronousQueue  <Runnable>()  );

        

        for( int i = 0; i < 6; i++ )

        {

            threadPool.execute( new Runnable()

            {

                public void run()

                {

                    System.out.println( "Thread " + Thread.currentThread().getName() + " Start" );

                    

                    try{ Thread.sleep( 1000 ); } catch( Exception e ) {} 

                    

                    System.out.println( "Thread " + Thread.currentThread().getName() + " End" );

                }

            } );

        }

- 이렇게 하면 최대 Thread개수인 4개를 모두 사용하게 됨.

- for문을 통해 Thread 실행시 6개의 Thread가 실행되는데 최대 사용가능한 Thread 개수는 4개 이므로 실행중 

RejectedExecutionException() 발생함.

SynchronousQueue 의 경우는 Task를 보관하지 않고 바로 실행하므로 최대 개수 4를 넘는 Thread 실행시 Exeption 발생함. )


참고 Url : http://blog.naver.com/jjoommnn/130109918061

'안드로이드 > Thread' 카테고리의 다른 글

ExecutorService  (0) 2015.12.08
ThreadPoolExecutor 사용하기.  (0) 2014.01.17
Posted by 파워킴