Callable과 Future

Callable

  • Runnable과 유사하지만 리턴 값을 받을 수 있다.

 

Future

 

get()

  • 결과를 가져오기
  • 블록킹 콜이다.
  • 타임아웃(최대한으로 기다릴시간)을 설정할 수 있다.
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newSingleThreadExecutor();

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

        // submit 메소드 - <T> Future<T> submit(Callable<T> task);
        Future<String> helloFuture = executorService.submit(hello);
        System.out.println("Started!");

        helloFuture.get();   // 블록킹 콜

        System.out.println("End!");
        executorService.shutdown();
    }

 

isDone()

  • 작업상태 확인하기 
  • 완료했으면 true 아니면 false를 리턴한다.
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newSingleThreadExecutor();

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

        // submit 메소드 - <T> Future<T> submit(Callable<T> task);
        Future<String> helloFuture = executorService.submit(hello);
        System.out.println("Start!, isDone? :" + helloFuture.isDone());
        
        helloFuture.get();   // 블록킹 콜

        System.out.println("End!, isDone? :" + helloFuture.isDone());
        executorService.shutdown();
        
//        출력
//        Start!, isDone? :false
//        (2초 후) - 블록킹 콜
//        End!, isDone? :true
    }

 

cancel()

  • 작업 취소하기
  • 취소 했으면 true 못했으면 false를 리턴한다.
  • parameter로 true를 전달하면 현재 진행중인 Thread를 Interrupt하고 그러지 않으면 현재 진행중인 작업이 끝날 때 까지 기다린다.
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newSingleThreadExecutor();

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

        // submit 메소드 - <T> Future<T> submit(Callable<T> task);
        Future<String> helloFuture = executorService.submit(hello);
        System.out.println("Start!, isDone? :" + helloFuture.isDone());


        helloFuture.cancel(true);
        // cancel한 후 get을 하게 되면 java.util.concurrent.CancellationException이 발생한다.
        // helloFuture.get();

        System.out.println("End!, isDone? :" + helloFuture.isDone());
        executorService.shutdown();

//        출력
//        Start!, isDone? :false
//        End!, isDone? :true (cancel을 하게 되면 isDone은 ture를 반환한다.)
    }

 

invokeAll()

  • 여러 작업 동시에 실행하기
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
//		ExecutorService executorService = Executors.newFixedThreadPool(4);
        Callable<String> test1 = () ->{
            Thread.sleep(1000L);
            return "Test1";
        };
        Callable<String> test2 = () ->{
            Thread.sleep(2000L);
            return "Test2";
        };
        Callable<String> test3 = () ->{
            Thread.sleep(3000L);
            return "Test3";
        };
        Callable<String> test4 = () ->{
            Thread.sleep(4000L);
            return "Test4";
        };
        long start = System.currentTimeMillis();
        List<Future<String>> list = 
                executorService.invokeAll(Arrays.asList(test1, test2, test3, test4));
        long end = System.currentTimeMillis();
        for(Future<String> future : list){
            System.out.println(future.get());
        }
        System.out.println("경과 : " + (end - start) / 1000);
//        출력
//        Test1
//        Test2
//        Test3
//        Test4
//        경과 : 10

//        만약 스레드가 4개라면 4초가 걸린다.
        executorService.shutdown();
    }

 

invokeAny()

  • 여러 작업중에 하나라도 먼저 응답이오면 끝내기
  • 동시에 실행한 작업중에 제일 짧게 걸리는 작업 만큼 시간이 걸린다.
  • 블록킹 콜이다.
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(1);

        Callable<String> test2 = () ->{
            Thread.sleep(2000L);
            return "Test2";
        };
        Callable<String> test4 = () ->{
            Thread.sleep(4000L);
            return "Test4";
        };
        Callable<String> test1 = () ->{
            Thread.sleep(1000L);
            return "Test1";
        };
        Callable<String> test3 = () ->{
            Thread.sleep(3000L);
            return "Test3";
        };
        long start = System.currentTimeMillis();
        String s =
                executorService.invokeAny(Arrays.asList(test1, test2, test3, test4));
        long end = System.currentTimeMillis();
        System.out.println(s);
        System.out.println("경과 : " + (end - start) / 1000);
//        출력
//        Test1
//        경과 : 1

        executorService.shutdown();
    }

 

 

 

 

더 자바, Java 8 - 인프런

자바 8에 추가된 기능들은 자바가 제공하는 API는 물론이고 스프링 같은 제 3의 라이브러리 및 프레임워크에서도 널리 사용되고 있습니다. 이 시대의 자바 개발자라면 반드시 알아야 합니다. 이

www.inflearn.com

'기록 > JAVA' 카테고리의 다른 글

[JAVA8] 어노테이션의 변화  (0) 2021.01.17
[JAVA8] CompletableFuture  (0) 2021.01.17
Executors  (0) 2021.01.16
Thread  (0) 2021.01.16
[JAVA8] Date 와 Time  (0) 2021.01.14