Java

[Java8] Callable과 Future

나프초 2024. 8. 29. 20:55

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