블로킹 방식이란?
무언가를 요청을 하고 나서 요청의 결과가 나올때까지 기다리는 방식을 이야기 한다.
블로킹 방식의 작업 완료 통보 받기
리턴타입 |
메소드명(매개변수) |
설명 |
Future<?> |
submit(Runnable task) |
- Runnable 또는 Callable을 작업 큐에 저장 - 리턴된 Future를 통해 작업 처리 결과를 얻는다. |
Future<?> |
submit(Runnable task, V result) |
|
Future<?> |
submit(Callable<V> task) |
Future
-작업 결과가 아니라 지연완료(pending completion)객체
-작업이 완료될 때까지 기다렸다가 최종 결과를 얻기 위해서 get()메소드를 사용한다.
리턴타입 |
메소드명(매개변수) |
설명 |
V |
get() |
작업이 완료될 때까지 블로킹 되어있다가 처리결과 V를 리턴 |
V |
get(long timeout, TimeUnit unit) |
timeout 시간동안 작업이 완료되면, 결과 V를 리턴하지만, 작업이 완료되지 않으면 TimeoutException을 발생시킴 |
메소드 |
작업 처리 완료후 리턴 타입 |
작업 처리 도중 예외 발생 |
submit(Runnable task) |
future.get() -> null |
future.get() -> 예외 발생 |
submit(Runnable task, Integer result) |
future.get() -> int 타입 값 |
future.get() -> 예외 발생 |
submit(Callable<String> task) |
future.get() -> String 타입 값 |
future.get() -> 예외 발생 |
*submit(Runnable task)
Runnable 객체는 결과 값이 없는 작업객체를 말한다. 따라서 결과가 없기 때문에 future.get()은 null을 리턴
*submit(Runnable task, Integer result)
Integer result는 스레드가 작업을 처리한 후의 결과값을 말한다. 따라서 future.get()은 int 타입 값을 리턴
*submit(Callable<String> task)
Callable의 작업 처리 결과가 String으로 나온다는 뜻이고, future.get()은 String타입 값을 리턴한다.
get()은 "스레드가 작업을 완료할 때까지 멈춰서 기다린다"는 뜻이다.
따라서
Future의 get()은 UI 스레드에서 호출하면 안된다.
-UI를 변경하고 이벤트를 처리하는 스레드가 get()메소드를 호출하면
-작업을 완료하기 전까지는 UI를 변경할 수 도 없고, 이벤트를 처리할 수도 없게 된다.
-따라서 다음과 같이 두가지 방법으로 get()메소드를 호출 할 수 있다.
1) 새로운 스레드를 생성해서 호출 |
2) 스레드 풀의 스레드가 호출 |
new Thread(new Runnable() { @Override public void run() { try { future.get(); } catch(Exception e) { e.printStackTrace(); } } }).start(); |
executorService.submit(new Runnable() { @Override public void run() { try{ future.get(); } catch(Exception e) { e.printStackTrace(); } } }); |
1) 새로운 스레드를 익명객체로 즉시 생성하여 바로 start()메소드로 실행하기
2) future.get()을 처리하는 작업 객체인 Runnable객체를 만들어서 스레드 풀의 스레드가 작업을 처리하도록 요청한다.
다른 메소드
리턴타입 |
메소드명(매개변수) |
설명 |
boolean |
cancel(boolean mayInterruptIfRunning) |
작업 처리가 진행중일 경우 취소시킴 |
boolean |
isCancelled() |
작업이 취소되었는지 여부 |
boolean |
isDone() |
작업 처리가 완료되었는지 여부 |
리턴값이 없는 작업 완료 통보
Runnable task = new Runnable() {
@Override
public void run() {
//스레드가 처리할 작업 내용
}
};
Future future = executorService.submit(task);
try {
future.get();
} catch(InterruptedException e) {
//작업 처리 도중 스레드가 interrupt 될 경우 실행할 코드
} catch(ExecutionException e) {
//작업 처리 도중 예외가 발생된 경우 실행할 코드
}
1) 리턴값이 없는 작업 객체(Runnable)를 만든다.
2) 작업 객체 task를 매개변수로 하여 submit메소드로 작업객체를 작업 큐에 넣어준다.
이때, submit메소드는 Future라는 객체를 리턴한다.
3) future를 가지고 스레드가 작업을 완료했는지, 처리도중인지 알 수 있다.
4) future.get(); 스레드가 작업을 완료할 때 까지 기다린다 는 뜻으로 get을 호출하게 되면 블로킹이 발생하게 되고,
스레드 풀의 스레드가 작업을 완료할 때 까지 future.get()메소드를 실행한 스레드는 멈춰있게 된다.
여기서는 작업 결과가 없기 때문에 future.get()은 null을 리턴한다 따라서 값을 담을 변수도 필요하지 않다.
5) get()메소드에서 발생할 수 있는 예외는 두가지이다.
InterruptedException, ExecutuionException
본 포스팅은 이것이 자바다 책을 참고하여 작성하였습니다.
'Java 공부' 카테고리의 다른 글
12장 스레드풀(4) (0) | 2018.12.12 |
---|---|
12장 스레드풀(3) (0) | 2018.12.11 |
12장 스레드풀(1) (0) | 2018.12.09 |
12장 스레드 그룹 (0) | 2018.12.09 |
12장 데몬 스레드 (0) | 2018.12.08 |