* Executor는 굉장히 단순한 인터페이스로 보이지만 아주 다양한 여러 가지 종류의 작업 실행 정책을 지원하는* 유연하면서도 강력한 비동기적 작업 실행 프레임웍의 근간을 이루는 인터페이스다* Executor는 작업등록(task submission) ,작업실행(task Execution)을 분리하는 표준적인 방법이며,* 각 작업은 Runnable의 형태로 정의한다.* Executor인터페이스를 구현한 클래스는 작업의 라이프 사이클을 관리하는 기능도 갖고 있고,* 몇가지 통계값을 뽑아내거나 애플리케이션에서 작업 실행 과정을 관리하고 모니터링하기 위한 기능도 갖고 있다.** Executor의 구조는 프로듀서-컨슈머 패턴에 기반하고 있으며, 작업을 생성해 등록하는 클래스가* 프로듀서(처리해야할 작업을 생성하는 주체)가 되고, 작업을 실제로 실행하는 스레드가컨슈머(생성된 작업을 처리하는 주체)가 되는 모양을 갖추고 있다.* 일반적으로 프로듀서-컨슈머 패턴을 애플리케이션에 적용해 구현할 수 있는 가장 쉬는 방법이바로 Executor 프레임웍을 사용하는 방법이다.
- 처리할 작업이 등록되면 그에 따라 실제 작업할 스레드를 하나씩 생성한다.- 생성할 수 있는 스레드의 최대 개수는 제한되어 있다.- 제한된 개수까지 스레드를 생성하고 나면 더이상 생성하지 않고 스레드 수를 유지한다.
- 캐시 스레드풀은 현재 풀에 갖고 있는 스레드의 수가 처리할 작업의 수보다 많아서 쉬는 스레드가 많이 발생할 때 쉬는 스레드를종료시켜 훨씬 유연하게 대응 할 수 있으며, 처리할 작업의 수가 많이 지면 필요한 만큼 스레드를 새로 생성한다.- 스레드의 수에 제한을 두지 않는다.
- 단일 스레드로 동작하는 Executor 로서 작업을 처리하는 스레드가 단 하나 뿐이다.- 만약 작업중에 Exeception 이 발생해 비정상적으로 종료되면 새로운 스레드를 하나 생성해 나머지 작업을 실행한다.- 등록된 작업은 설정된 큐에서 지정하는 순서(FIFO,LIFO,우선순위)에 따라 반드시 순차적으로 처리된다.
- 일정시간 이후에 실행하거나 주기적으로 작업을 실행할 수 있으며, 스레드의 수가 고정되어 있는 형태의Executor.Timer 클래스의 기능과 유사하다.
- newFixedThreadPool,newCachedThreadPool 팩토리 메소드는 일반화된 형태로 구현되어 있는 ThreadPoolExecutor클래스의 인스턴스를 생성한다.- 생성된 ThreadPoolExecutor 인스턴스에 설정값을 조절해 필요한 형태를 갖추고 사용할 수도 있다.- Executor 를 구현한 클래스는 대부분 작업을 처리하기 위한 스레드를 생성하도록 되어 있다. 하지만 JVM 은 모든 스레드가종료되기 전에는 종료하지 않고 대기하기 때문에 Executor를 제대로 종료시키지 않으면 JVM 자체가 종료되지 않고대기하기도 한다.- Executor는 작업을 비동기적으로 실행하기 때문에 앞서 실행시켰던 작업의 상태를 특정시점에 정확히 파악하기가 어렵다.어떤작업은 이미 완료되었을 수도 있고, 몇몇 작업은 실행중일 수 있고, 또다른 작업은 큐에서 대기하고 있을 수 있다.- 애플리케이션을 종료하는 과정을 보면 안정한 종료방법과(작업을 새로 등록하지 못하고, 시작된 모든작업이 끝날때 까지 기다림)강제적인 종료 방법이 있겠다. 물론 그사이에 위치하는 여러가지 종료방법이 있겠다.- Executor가 애플리케이션에 스레드 풀등의 서비스를 제공한다는 관정으로 생각해 보면 Executor 역시 안전한 방법이든,강제적인 방법이든 종료절차를 밟아야할 필요가 있다.- 그리고 종료절차를 밟는 동안 실행중이거나,대기중인 작업을 어떻게 처리했는지 애플리케이션에 알려줄 의무가 있다.- 이처럼 서비스를 실행하는 동작주기와 관련해 Ececutor를 상속받은 ExecutorService 인터페이스에는 동작주기를 관리할 수 있는 여러가지 메소드가 추가되어 있다.
public interface ExecutorService extends Executor{void shutdown(); --> 안전한 종료List<Runnable> shutdownNow(); --> 강제종료boolean isShutdown();boolean isTerminated();boolean awaitTermination(long timeout,TimeUnit unit) throw InterruptedExeception;--> ExecutorService가 종료상태로 들어갈 때까지 기다리고자 할때 사용..,}보통 shutdown() 메소드 실행 후 바로 awaitTermination()을 실행하면 Executor를 직접 종료시키는것과비슷한 효과를 얻을 수 있다.
ExecutorService exec= Executors.newFixedThreadPool(100);Callable<V> task = new Callable<V>() {public V call() throws Exception {return null;}};Future<V> a = exec.submit(task);a.get();
* ThreadPoolExecutor :
* Executors 클래스에 들어있는 newCachedThreadPool, newFixedThreadPool ,newScheduledThreadPool
* 과 같은 팩토리메소드에서 생성해 주는 Executor에 대한 기본적인 내용이 구현되어 있는 클래스이다.
* 팩토리메소드를 사용해 만들어진 스레드 풀의 기본 실행 정책이 요구 사항에 잘 맞지 않는다면 ThreadPoolExecutor 클래스의
* 생성자를 직접 호출해 스레드 풀을 생성할 수 있으며, 생성자에 넘겨주는 값을 통해 스레드 풀의 설정을 마음대로 조절할 수 있다.
public ThreadPoolExecutor (int corePoolSize, // 스레드풀을 사용할때 원하는 스레드의 개수
int maximumPoolSize, //동시에 동작할 수 있는 스레드의 최대값
long keepAliveTime, //스레드의 유지시간
TimeUnit unit,
BlokingQueue<Runable> workQueue,
ThreadFactory threadFactory,
RehectedExecutionHandler handker)
{....}
* newFixedThreadPool
* - 스레드풀의 코어크기,최대크기를 newFixedThreadPool(100) 처럼 파라미터로 지정한 값으로 설정
* - 시간제한은 무제한
* - LinkedBlokingQueue 사용
* newCachedThreadPool
* - 스레드풀의 최대 크기를 Integer.MAX_VALUE값으로 설정
* - 코어 크기 :0
* - 스레드 유지시간은 1분
* - SynchronousQueue 사용 : 프로듀소에서 생긴 작업을 컨슈머인 스레드에 직접 전달
* 따지고 보면 큐가 아니며, 단지 스레드 간에 작업을 넘겨주는 기능을 담당함
* - SynchronousQueue에 작업을 추가하려면 컨슈머인 스레드가 이미 작업을 받기위해 대기하고 있어야 하며,
* 대기중인 스레드가 없는 상태에서 스레드의 갯수가 최대 크기보다 작다면 새로운 스레드를 생성시켜 동작한다.
* 최대크기에 다다른 상태라면 작업을 거부하도록 되어 있다.
* 따라서 newCachedThreadPool에서 만들어낸 스레드풀은 크기가 무제한 늘어나며,
사용량이 줄어들면 스레드갯수가 적장히 줄어든다
'JAVA > JAVA 스레드' 카테고리의 다른 글
[java] 쓰레드의 우선순위 (0) | 2017.11.01 |
---|---|
[java] 싱글쓰레드와 멀티쓰레드 (0) | 2017.11.01 |
[java] start()와 run() (0) | 2017.11.01 |
[java] 쓰레드 구현 및 실행 (0) | 2017.11.01 |
[java] 프로세스와 쓰레드 (0) | 2017.11.01 |
스레드풀(CompletionService)을 이용하여 작업실행하기 (0) | 2016.03.09 |
자바 쓰레드 동기화 (syncronized 키워드 사용하기) (0) | 2016.03.09 |
JAVA Thread 사용하기 (0) | 2016.03.09 |