블로킹 방식의 작업 완료 통보_1
ExecutorService의 submit() 메소드는 Runnable, Callable 작업을 스레드 풀의 작업 큐에 저장하고 즉시 Future 객체를 리턴한다.
Future 객체는 작업이 완료될 때까지 기다렸다가(블로킹되었다가) 최종 결과를 얻는데 사용된다. (그래서 Future 객체를 지연 완료(pending completion)객체라고 한다.)
Future의 get() 메소드를 호출하면 스레드가 작업을 완료할 때까지 블로킹되었다가 작업을 완료하면 처리 결과를 리턴한다. (블로킹을 사용하는 작업 완료 통보 방식)
주의할 점은 Future의 get() 메소드는 스레드가 작업이 완료될때까지 블로킹되므로 다른 코드를 실행할 수 없다는 것이다. 따라서 get() 메소드를 호출하는 스레드는 새로운 스레드이거나 스레드풀의 또 다른 스레드가 되어야 한다.
새로운 스레드에서 호출
new Thread(new Runnable(){
@Override
public void run(){
try{
future.get();
}catch(Exception e){
}
}
}).start();
스레드풀의 스레드가 호출
executorService.submit(new Runnable(){
@Override
public void run(){
try{
future.get();
}catch(Exception e){
}
}
});
리턴값이 없는 작업 완료 통보
리턴값이 없는 작업일 경우 Runnable 객체를 이용한다.
결과값이 없는 작업 처리 요청은 submit(Runnable task) 을 이용하면 된다. 결과값이 없어도 Future 객체를 리턴하는데 이는 스레드가 작업 처리를 정상적으로 완료했는지, 예외가 발생했는지 확인하기 위해서이다.
정상적일 경우 => null 리턴
스레드가 작업 중 예외가 발생할 경우 => 예외를 발생시킴
Runnable task = new Runnable(){
@Override
public void run(){
// 스레드가 처리할 작업 내용
}
}
Futrue future = executorService.submit(task);
try{
future.get();
}catch(InterruptedException e){
// 작업 도중 스레드가 interrupt될 경우
}catch(ExecutionException e){
// 작업 처리 도중 예외가 발생한 경우
}
1부터 10까지의 합을 출력하는 작업(스레드 풀에 요청)
public class NoResultExample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
System.out.println("processors : " + Runtime.getRuntime().availableProcessors());
System.out.println("=작업 처리 요청=");
Runnable runnable = new Runnable() {
@Override
public void run() {
int sum = 0;
for(int i=0; i<=10; i++){
sum += i;
}
System.out.println("=처리 결과= " + sum);
}
};
Future future = executorService.submit(runnable);
try{
future.get();
System.out.println("=작업 처리 완료=");
}catch(Exception e){
System.out.println("=실행 예외 발생함=");
}
executorService.shutdown();
}
}
리턴값이 있는 작업 완료 통보
스레드가 작업을 완료한 후에 애플리케이션이 처리 결과를 얻어야 된다며 작업 객체를 Callable생성하면 된다.
submit() 메소드는 작업 큐에 Callable 객체를 저장하고 즉시 Future
스레드가 Callable 객체의 call() 메소드를 모두 실행하고 T 타입의 값을 리턴하면, Future
Callable<T> task = new Callable<T>(){
@Override
public T call() throws Exception{
// 스레드가 처리할 작업 내용
return T;
}
}
Future<T> future = executorService.submit(task);
try{
T result = future.get();
}catch(InterruptedException e){
// 작업 도중 스레드가 interrupt될 경우
}catch(ExecutionException e){
// 작업 처리 도중 예외가 발생한 경우
}
public class ResultByCallableExample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
System.out.println("=작업 처리 요청=");
Callable<Integer> task = new Callable<Integer>() {
@Override
public Integer call() {
int sum = 0;
for(int i=0; i<=10; i++){
sum += i;
}
return sum;
}
};
Future<Integer> future = executorService.submit(task);
try{
int sum = future.get();
System.out.println("=처리결과= " + sum);
System.out.println("=작업 처리 완료=");
}catch(Exception e){
System.out.println("=실행 예외 발생함=");
}
executorService.shutdown();
}
}
'프로그래밍 노트 > JAVA' 카테고리의 다른 글
[JAVA] 콜백 방식의 작업 완료 통보 (스레드풀_4) (0) | 2019.03.16 |
---|---|
[JAVA] 블로킹 방식의 작업 완료 통보_2 (스레드풀_3) (0) | 2019.03.16 |
[JAVA] 스레드풀 생성, 종료 및 작업 처리 (스레드풀_1) (0) | 2019.03.14 |
[JAVA] 스레드 그룹(thread group) (0) | 2019.03.13 |
[JAVA] interrupt() 메소드를 이용하여 스레드 정지시키기 (0) | 2019.03.04 |