[Java] Callable과 Future

nathan·2022년 1월 27일
0

JAVA

목록 보기
38/45

Callable과 Future

Callable

  • Runnable과 유사하나, 작업의 결과를 받아볼 수 있다는 차이가 있다.

Future

Callable과 Future 사용 예시(get, isDone, cancel)

import java.util.concurrent.*;

public class FutureExercise {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newSingleThreadExecutor();

        Callable<String> hello = () -> {
            Thread.sleep(2000L);
            System.out.println("RUNNING");
            return "Hello";
        };

        // 정의한 Callable을 사용하는 방법
        Future<String> submit = executorService.submit(hello);
        System.out.println("Started!");
        System.out.println(submit.isDone()); // 끝났으면 true, 안 끝났으면 false
        submit.get(); // get을 만난 순간부터 멈춰서 기다림(블록킹이라고 함).

        // 마냥 기다리기만 하는것이 아니라 상태도 확인할 수 있음
        System.out.println(submit.isDone()); // 끝났으면 true, 안 끝났으면 false

        // 진행중인 작업을 취소하는 기능도 제공됨
        // parameter로 true를 주면 현재 진행 중인 작업을 interrupt하면서, 종료
        // false는 현재 진행 중인 작업을 기다리고, 종료
        // 일단 cancel을 하고나면, get을 통해 가져오는것은 불가능해짐.
        // 그리고 cancel을 하고나면, isDone은 true가 됨.(값을 가져갈 수 있다는 의미의 종료가 아닌 캔슬로 인한 종료)
        submit.cancel(true);

        System.out.println("End!");
        executorService.shutdown();
    }
}
>>>
Started!
false
RUNNING
true
End!
  • Future<T> get() : Future 타입으로 결과를 가져오는 메서드, 타임아웃(최대한으로 기다릴 시간)을 설정할 수 있다.
    • 블록킹 콜이다.
  • boolean isDone() : 상태를 확인할 수 있는 메서드, 만약 작업이 끝났으면 true, 끝나지 않았으면 false를 return한다.
  • boolean cancel() : 작업을 취소하는 메서드로써, 취소에 성공하면 true, 못했으면 false를 리턴한다.
    • parameter로 true를 전달하면, 현재 진행중인 스레드를 interrupt하여 작업을 중단시키고, 그렇지 않으면 현재 진행중인 작업이 끝날때까지 기다린다.

Callable과 Future 사용 예시(invokeAll, invokeAny)


import java.util.List;
import java.util.Arrays;
import java.util.concurrent.*;

public class FutureExercise2 {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
//        ExecutorService es = Executors.newSingleThreadExecutor();
        ExecutorService es = Executors.newFixedThreadPool(4);

        Callable<String> hello = () -> {
            Thread.sleep(2000L);
            return "Hello";
        };

        Callable<String> java = () -> {
            Thread.sleep(3000L);
            return "Java";
        };

        Callable<String> nathan = () -> {
            Thread.sleep(1000L);
            return "Nathan";
        };

        // 여러 Callable을 한꺼번에 보낼 수 있음 : invokeAll, invokeAny
        // invokeAll : 그러나 모든 작업이 끝날때까지 기다린 후 결과를 가져옴
//        List<Future<String>> futures= es.invokeAll(Arrays.asList(hello, java, nathan));
//        for (Future<String> f : futures){
//            System.out.println(f.get());
//        }
        // invokeAny : 바로 가장 빨리 끝난 결과가 나옴(Future가 아닌, 바로 그 타입으로)
        String futures2= es.invokeAny(Arrays.asList(hello, java, nathan));
        System.out.println(futures2); // 싱글스레드일때는 기다린 초가 가장 짧은것과 별개로 가장 먼저 실행한게 나오는듯?
        // 스레드 여러개를 만들었을 때는 기다린 초가 가장 짧은게 출력되었음.


        es.shutdown();
    }
}
>>>
Nathan
  • invokeAll() : 여러 작업을 동시에 실행한뒤 결과를 가져오는 메서드. 동시에 실행한 작업 중에 제일 오래 걸리는 작업만큼 시간이 걸린다.

  • invokeAny() : 여러 작업 중에 하나라도 먼저 응답이 오면 끝내는 메서드. 동시에 실행한 작업 중에 제일 짧게 걸리는 작업만큼 시간이 걸린다.

    • 블록킹 콜이다.
profile
나는 날마다 모든 면에서 점점 더 나아지고 있다.

0개의 댓글