웹사이트 검색

Java Callable Future 예제


Java Callable 및 Future는 다중 스레드 프로그래밍에서 많이 사용됩니다. 지난 몇 개의 게시물에서 우리는 자바 스레드에 대해 많은 것을 배웠지만 때때로 우리는 스레드가 우리가 사용할 수 있는 어떤 값을 반환할 수 있기를 바랍니다. Java 5는 Runnable 인터페이스와 유사한 동시성 패키지에 java.util.concurrent.Callable 인터페이스를 도입했지만 모든 객체를 반환할 수 있고 예외를 발생시킬 수 있습니다.

자바 호출 가능

자바 미래

Java Callable 작업은 java.util.concurrent.Future 개체를 반환합니다. Java Future 객체를 사용하여 Callable 작업의 상태를 확인하고 반환된 객체를 가져올 수 있습니다. Callable이 완료될 때까지 기다린 다음 결과를 반환할 수 있는 get() 메서드를 제공합니다. Java Future는 관련된 Callable 작업을 취소하는 cancel() 메서드를 제공합니다. 결과를 기다리는 시간을 지정할 수 있는 오버로드된 버전의 get() 메서드가 있습니다. 현재 스레드가 더 오랜 시간 동안 차단되는 것을 방지하는 데 유용합니다. 연관된 Callable 태스크의 현재 상태를 찾기 위한 isDone() 및 isCancelled() 메소드가 있습니다. 다음은 1초 후에 작업을 실행하는 스레드의 이름을 반환하는 Java 호출 가능 작업의 간단한 예입니다. 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<String> {

    @Override
    public String call() throws Exception {
        Thread.sleep(1000);
        //return the thread name executing this callable task
        return Thread.currentThread().getName();
    }
    
    public static void main(String args[]){
        //Get ExecutorService from Executors utility class, thread pool size is 10
        ExecutorService executor = Executors.newFixedThreadPool(10);
        //create a list to hold the Future object associated with Callable
        List<Future<String>> list = new ArrayList<Future<String>>();
        //Create MyCallable instance
        Callable<String> callable = new MyCallable();
        for(int i=0; i< 100; i++){
            //submit Callable tasks to be executed by thread pool
            Future<String> future = executor.submit(callable);
            //add Future to the list, we can get return value using Future
            list.add(future);
        }
        for(Future<String> fut : list){
            try {
                //print the return value of Future, notice the output delay in console
                // because Future.get() waits for task to get completed
                System.out.println(new Date()+ "::"+fut.get());
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
        //shut down the executor service now
        executor.shutdown();
    }

}

위의 프로그램을 실행하면 java Future get() 메서드가 자바 호출 가능 작업이 완료되기를 기다리기 때문에 출력이 지연되는 것을 알 수 있습니다. 또한 이러한 작업을 실행하는 스레드는 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
...

팁: 예를 들어 get() 메서드를 무기한 기다리지 않고 기본 시간 후에 시간 초과하도록 재정의하는 것과 같이 Java Future 인터페이스의 일부 메서드를 재정의하려는 경우에는 어떻게 해야 합니까? 이 경우 Java FutureTask 클래스가 유용합니다. 이것이 Future 인터페이스의 기본 구현입니다. 이 클래스에 대해 자세히 알아보려면 Java FutureTask 예제를 확인하세요.