Java Callable Future 예제

Java Callable 및 Future는 다중 스레드 프로그래밍에서 많이 사용됩니다. 지난 몇 게시물에서는 자바 스레드에 대해 많이 배웠지만 때로는 스레드가 사용할 수 있는 값을 반환할 수 있다면 좋겠다고 생각합니다. Java 5는 Runnable 인터페이스와 유사하지만 어떤 객체든 반환할 수 있고 예외를 throw할 수 있는 java.util.concurrent.Callable 인터페이스를 도입했습니다.

Java Callable

Java Callable 인터페이스는 반환 객체의 유형을 정의하기 위해 제네릭을 사용합니다. Executors 클래스는 스레드 풀에서 Java Callable을 실행하는 유용한 메서드를 제공합니다. 호출 가능한 작업이 병렬로 실행되므로 반환된 객체를 기다려야 합니다.

Java Future

Java Callable 작업은 java.util.concurrent.Future 개체를 반환합니다. Java Future 개체를 사용하여 Callable 작업의 상태를 확인하고 반환된 개체를 얻을 수 있습니다. 이는 Callable 작업이 완료되기를 기다린 다음 결과를 반환하는 get() 메서드를 제공합니다. Java Future는 연관된 Callable 작업을 취소하기 위한 cancel() 메서드를 제공합니다. 결과를 기다리는 시간을 지정할 수 있는 get() 메서드의 오버로드된 버전도 있으며, 현재 스레드가 긴 시간 동안 차단되는 것을 피하는 데 유용합니다. 연관된 Callable 작업의 현재 상태를 확인하기 위해 isDone()isCancelled() 메서드가 있습니다. 여기에는 1초 후에 작업을 실행하는 스레드의 이름을 반환하는 Java Callable 작업의 간단한 예제가 있습니다. 우리는 Executor 프레임워크를 사용하여 100개의 작업을 병렬로 실행하고 Java Future를 사용하여 제출된 작업의 결과를 얻고 있습니다.

package com.journaldev.threads;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class MyCallable implements Callable {

    @Override
    public String call() throws Exception {
        Thread.sleep(1000);
        //이 호출 가능한 작업을 실행하는 스레드 이름 반환
        return Thread.currentThread().getName();
    }
    
    public static void main(String args[]){
        //Executors 유틸리티 클래스에서 ExecutorService 가져오기, 스레드 풀 크기는 10
        ExecutorService executor = Executors.newFixedThreadPool(10);
        //Callable에 연관된 Future 객체를 보유하는 목록 만들기
        List> list = new ArrayList>();
        //MyCallable 인스턴스 생성
        Callable callable = new MyCallable();
        for(int i=0; i< 100; i++){
            //스레드 풀에서 실행될 Callable 작업 제출
            Future future = executor.submit(callable);
            //Future를 목록에 추가하여 Future를 사용하여 반환 값을 얻을 수 있음
            list.add(future);
        }
        for(Future fut : list){
            try {
                //Future의 반환 값을 출력하면 콘솔에서 출력 지연이 발생합니다
                //Future.get()이 작업이 완료될 때까지 기다리기 때문입니다
                System.out.println(new Date()+ "::"+fut.get());
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
        //지금 executor 서비스를 종료합니다
        executor.shutdown();
    }

}

위의 프로그램을 실행하면 java Future get() 메소드가 java callable 작업이 완료될 때까지 기다리기 때문에 출력이 지연됨을 알 수 있습니다. 또한 이러한 작업을 실행하는 스레드가 10개뿐임을 유의하십시오. 다음은 위 프로그램의 일부 출력 스니펫입니다.

Mon Dec 31 20:40:15 PST 2012::pool-1-thread-1
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-2
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-3
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-4
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-5
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-6
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-7
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-8
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-9
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-10
Mon Dec 31 20:40:16 PST 2012::pool-1-thread-2
...

: Java Future 인터페이스의 일부 메소드를 재정의하려면 어떻게 해야 할까요? 예를 들어, 기본 시간이 경과한 후에 무한정 기다리지 않고 get() 메소드를 제한하는 경우 Java FutureTask 클래스가 유용합니다. 이 클래스는 Future 인터페이스의 기본 구현체입니다. 이 클래스에 대해 더 알아보려면 Java FutureTask 예제를 확인하십시오.

Source:
https://www.digitalocean.com/community/tutorials/java-callable-future-example