jdk1.5.x 버전부터
java.util.concurrent 패키지를 제공하고 있다.
패키지 하위에 유용한 클래스들이 많이 존재하므로
계속해서 살펴보고 익혀야 겠다.
Java5에서 Thread pool을 사용하는 방법이다.
이전 jdk버전에서는 Thread pool을 직접구현해야 했고,
구현을 한다해도, 검증되지 않은 성능 Issue는 항상 개발자를 머리아프게 했었는데...
정말 Good이군~~
private int threadCount=5;
private ExecutorService executorService;
/** thread 숫자를 설정한다. 초기치는 5개 */
public void setThreadCount(int threadCount) {
this.threadCount = threadCount;
}
- Thread Pool생성
if (executorService==null) {
logger.debug("Creating new thread pool for message delivery");
executorService = Executors.newFixedThreadPool(threadCount);
}
- Thread 실행
/* Spawn a task into the thread pool. */
executorService.execute(new Runnable(){
public void run() {
//some code that takes some time to run.
}
});
정말 간단하다.
물론 실제 로직에 적용하기 위해선 부가적으로 추가해야 할것들이 있지만
우선 jdk기본 패키지에 포함되었다는것은 성능검증은 완료된것이라 봐야 하므로
의심없이 사용할 수 있을듯 하다.(물론 테스트는 해봐야 한다.)
만든이가 너무 고맙다!
출처 -
http://jace.tistory.com/70
쓰레드란, 자바에서 유일하게 제공되는 병렬처리용 컨트롤 방식이다. (자바는 프로세스를
fork 할 수 없음)
병렬처리를 위해서 쓰레드를 생성하지만, 쓰레드가 반복적으로 생성, 소멸 과정을 거친다면
단순 쓰레드를 생성하는 방식으로는 리소스를 많이 사용하기 때문에 비 효율적이다. 이때
고려될 방법이 미리 쓰레드를 생성해 놓고, 메모리에서 호출하는 방식인 쓰레드 풀 기법을
사용하면 보다 효율적으로 쓰레드를 사용할 수 있다.
쓰레드풀은 갠적으로 구현해서 사용해도 좋으나, 자바에서 기본적으로 제공하는 검증 된
쓰레드 풀을 사용하는 것을 추천한다.
1. Executor 생성(10개의 풀)
final ExecutorService taskExecutor = Executors.newFixedThreadPool(10);
//=====>반복시작
2. 쓰레드로 만들고자 하는 클래스 오브젝트 생성
Runnable myRunnable= new Runnable(){
public void run(){
MyThread myThread = new MyThread();
}
};
3. 쓰레드 실행
taskExecutor.execute(myRunnable);
//=====>반복종료
4.쓰레드로 생성되는 클래스는 Runnable Interface 를 Implements 하는 방식으로 구현 한다.
public class MyThread implements Runnable {
public MyThread()
{
}
public void run()
{
}
}
[출처] 자바 쓰레드 풀 사용하기|작성자 냅시스
출처 -
http://blog.naver.com/rainbowhand?Redirect=Log&logNo=13012901119
자바 1.5 버전 부터 쓰래드를 지원하기 위한 API가 강력해진거 같다.
모, 일단 라이브러리가 많이 늘어난거 같다. 래치, 배리어, 쓰레드풀 , 퓨처패턴 등등등......
나중에 필요할때 써 먹을라고, 관련되는 녀석 공부하던중에
자바 1.5부터 지원되는 쓰레드풀 생성하는 아주작은 샘플을 만들어 보았습니당~
/**
*
*/
package test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author 이준성
*
*/
public class ThreadPoolTest {
final static int THREADCOUNT = 10;
/**
* @param args
*/
public static void main(String[] args) {
// 쓰레드 풀 생성. THREADCOUNT 개수 만큼
ExecutorService exec = Executors.newFixedThreadPool(THREADCOUNT);
for(int i = 0 ; i<THREADCOUNT*2 ; i++) {
exec.execute(new TestThread());
}
// 쓰레드풀 생성하고 전부다 사용후에는 반드시 셧다운 해야함~
exec.shutdown();
}
// 테스트 쓰래드
public static class TestThread implements Runnable{
public void run() {
for(int i=1 ; i<= 100 ; i++) {
System.out.println(Thread.currentThread().getName() + " => "+i);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
Executors.newFixedThreadPool(THREADCOUNT) 이 부분에 의해서 쓰레드 풀을 생성해서 풀을 넘겨 줍니다.
사실 이거말고도 Executors클래스로 생성할수 있는 쓰레드 풀이 3개가 더 존재하더군요.
캐쉬, 싱글익스큐트 등등.
Executors.newFixedThreadPool 이 녀석에 의해서 생성되는 쓰레드 풀은 작업이 하나하나 등록할때마다 새로운 쓰레드를 생성한다고 합니다.
작업을 등록하는 부분은 exec.execute(new TestThread()) 이 부분 입니다.
쓰레드 풀을 사용하지 않을 경우는 Thread를 상속받던가 Runnable을 구현해서 생성하고 스타트 했지만, 쓰레드풀에 작업을 등록하려면 Runnable 이녀석을 구현해서 인자로 넘겨 주기만 하면 됩니다.
또 모든 작업이 끝날시에는 셧다운을 해야하는데, 쓰레드 풀 특성을 곰곰히 생각해보시면, 쉽게 아실거라 생각이 듭니다.
쓰레드풀 자체에서 쓰레드 관리(?) 하기 위한 쓰레드가 생성이 되기 때문에, 셧다운을 해주셔야 합니다. 하지않으면~ 프로세스가 남아있더군요.
셧다운 하는 방식도 여러가지가 있더군요. 모두 끝낸후에 셧다운 및 강제종료등등
위에서 사용한 방식은 모두 끝낸후에 종료입니다. 아~ 그리고 셧다운후에 작업을 등록하면 익셉션이 발생한다고 합니다.
쓰레드풀에서 퓨터 패턴도 적용되어서~ 작업이 끝난 후에 결과값도 받을수 있습니다.
서브밋이라는 메소드를 사용하면 되더군요.
시간날때, 다른형태의 쓰레드풀 사용하는 방법과 퓨쳐 패턴 사용방법을 올리지요~
출처 -
http://blog.naver.com/lover4908?Redirect=Log&logNo=110039084541
* 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에서 만들어낸 스레드풀은 크기가 무제한 늘어나며,
사용량이 줄어들면 스레드갯수가 적장히 줄어든다
출처 -
http://blog.naver.com/minis24?Redirect=Log&logNo=80152375114
ExecutorService 를 이용하여 간단하게 ThreadPool를 구현할 수 있다.
int poolSize = 10;
//고정 개수의 ThreadPool을 생성한다.(이외 다른 종류는 API를 참고한다.)
ExecutorService e = Executors.newFixedThreadPool(poolSize);
//실행을 할때 해당 작업의 완료 여부나 return 값을 알기 위해서는 submit을 이용하고 그외는 execute를 이용한다.
//단순 실행일때
e.execute(Runnalbe);
//작업 종료 여부를 알려고 할때
Future f = e.submit(Runnable);
f.isCancelled(); // 작업 종료하기 전 취소 되었는지 여부를 알수 있다 , true - 취소
f.isDone(); //작업이 성공적으로 종료되었으면 true
//return 값을 알고 싶을때
Future f = e.submit(Callable);
Object o = f.get(); // 작업이 완료될때까지 기다리며 완료 될때 return 값을 받는다.
[출처] ExecutorService 사용하기(JDK1.5 이상)|작성자 진성
출처 -
http://cafe.naver.com/withoracle.cafe?iframe_url=/ArticleRead.nhn%3Farticleid=1009&
Executor 는 어떤 작업을 처리하기 위한 스래드를 생성하는 녀석이다. 이 녀석이 만약 어떤 스래드가 죽어야 하는데 죽지 않고 대기 하는 상황이 생긴다면 JVM 도 죽지 않는다.
타스크를 실행하기 위해 쓰레드를 생성하는데
출처 -
http://joejeon.tistory.com/388
'Development > Java' 카테고리의 다른 글
인터페이스(interface) (0) | 2012.03.18 |
---|---|
DAO, DTO, VO (2) | 2012.03.16 |
java 어노테이션(Annotation) (0) | 2012.03.14 |
JVM 인코딩 설정(Dfile.encoding 옵션) (0) | 2012.03.13 |
자바빈즈(javabeans) (0) | 2012.03.11 |