Callable 과 Future
- Callable
- Runnable과 유사하지만 작업의 결과를 받을 수 있다는 점이 다르다.
- 어떤 쓰레드에서 작업을 실행했는데, 그 작업의 결과를 가져오고 싶을 때 Runnable은 리턴 타입이 void이기 때문에 불가능하다.
- 그럴 때 Callable을 사용하면 값을 리턴받을 수 있다.
- Future
- 비동기 작업의 아직 계산되지 않은 결과를 표현하는 인터페이스이다.
- Callable에서 리턴시켜주는 값이 Future이다.
- ExecutorService의 submit 메소드는 Callable이나 Runnable 객체를 인수로 받아서 비동기적으로 실행하며, 결과를 Future 객체로 반환한다.
주요 인터페이스
get()
ExecutorService executorService = Executors.newSingleThreadExecutor();
Callable<String> hello = () -> {
Thread.sleep(2000L);
return "Hello";
};
//ExecutorService가 Callable인 hello를 실행하고, 그 결과를 Future로 받는다.
Future<String> helloFuture = executorService.submit(hello);
System.out.println("Started!");
String result = helloFuture.get(); //값을 가져올 때 까지 멈춰서 기다린다.(블로킹 콜)
System.out.println(result);
System.out.println("End!");
executlrService.shutdown();
- 블록킹 콜이다. => 값을 가져올 때 까지 다음 코드가 실행되지 않고, 멈춰서 기다린다.
- 타임아웃(최대한으로 기다릴 시간)을 설정할 수 있다.
isDone()
- 작업 상태를 확인하여 완료했으면 true, 아니면 false를 리턴한다.
cancel()
- 작업을 취소한다. 취소가 되었으면 true, 못했으면 false를 리턴한다.
- parameter로 true를 전달하면 현재 진행중인 쓰레드를 interrupt하고, 그렇지 않으면 현재 진행중인 작업이 끝날 때까지 기다린다.
- 파라미터로 false를 주어 작업이 끝날 때 까지 기다린다고 하더라도, 일단 cancel을 호출하면 get()을 통해 값을 가져올 수 없다. get()에서 가져오면 에러가 발생한다.
- 또한 일단 cancel을 호출하면 isDone()은 무조건 true가 된다. 작업이 완료되었다기보다는 cancel에 의해 작업이 중단된 것이지만 동일하게 true가 찍힌다. 이 때는 isDone이 true여도 값을 가져올 수 없다.
invokeAll()
ExecutorService executorService = Executlrs.newFixedThreadPool(3);
Callable<String> One = () -> {
Thread.sleep(2000L);
return "One";
});
Callable<String> Two = () -> {
Thread.sleep(1000L);
return "Two";
});
Callable<String> Three = () -> {
Thread.sleep(3000L);
return "Three";
});
List<Future<String>> futures = executorService.invokeAny(Arrays.asList(One, Two, Three));
executorService.shutdown();
- 동시에 작업이 실행되고 모든 작업이 끝날 때 까지 기다려서 결과를 리스트로 받는다.
- 따라서 동시에 실행한 작업 중에 제일 오래걸리는 작업 만큼 시간이 걸린다.
invokeAny()
ExecutorService executorService = Executlrs.newFixedThreadPool(3);
Callable<String> One = () -> {
Thread.sleep(2000L);
return "One";
});
Callable<String> Two = () -> {
Thread.sleep(1000L);
return "Two";
});
Callable<String> Three = () -> {
Thread.sleep(3000L);
return "Three";
});
String s = executorService.invokeAny(Arrays.asList(One, Two, Three)); //블로킹콜
System.out.println(s); //Two 출력
executorService.shutdown();
- 동시에 작업이 실행되고 가장 빨리 끝난 작업의 결과를 리턴한다.
- 따라서 동시에 실행한 작업 중 제일 시간이 조금 걸리는 작업 만큼 시간이 걸린다.
- 블록킹 콜이다. => 값을 가져올 때 까지 다음 코드가 실행되지 않고, 멈춰서 기다린다.
이 포스팅은 더 자바, Java 8 강의를 수강하며 작성되었습니다.
더 자바, Java 8 강의 | 백기선 - 인프런
백기선 | 자바 8에 추가된 기능들은 자바가 제공하는 API는 물론이고 스프링 같은 제 3의 라이브러리 및 프레임워크에서도 널리 사용되고 있습니다. 이 시대의 자바 개발자라면 반드시 알아야 합
www.inflearn.com
'Java' 카테고리의 다른 글
[Java8] Annotation의 변화 (0) | 2024.09.02 |
---|---|
[Java8] CompletableFuture (0) | 2024.09.01 |
[Java8] Executors (0) | 2024.08.28 |
[Java8] Concurrent Programming (0) | 2024.08.27 |
[Java8] Date & Time API (1) | 2024.08.12 |