Runnable과 유사, 작업의 결과를 받을 수 있다.
비동기적인 작업의 현재 상태를 조회하거나 결과를 가져올 수 있다.
import java.util.concurrent.*;
public class App {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        Callable<String> hello = () -> {
            Thread.sleep(3000);
            return "hello";
        };
        Future<String> future = executorService.submit(hello);
        System.out.println(future.get()); // 3초 뒤 hello 출력
        executorService.shutdown();
    }
}	Future<String> future = executorService.submit(hello);
    System.out.println("Start");
    System.out.println(future.get());
    System.out.println("End");
    executorService.shutdown();get 메서드를 만나는 순간 Callable의 결과를 가져올 때까지 기다린다.
    Future<String> future = executorService.submit(hello);
    System.out.println("작업 상태 확인 : " + future.isDone());
    System.out.println("Start");
    System.out.println(future.get());
    System.out.println("작업 상태 확인 : " + future.isDone());
    System.out.println("End");
    executorService.shutdown();	Future<String> future = executorService.submit(hello);
    System.out.println("Start");
    future.cancel(false);
    System.out.println(future.isDone()); // true, false 둘 다 true 반환
    System.out.println(future.get());
    System.out.println("End");cancel()에 true를 넘겨주면 현재 진행 중인 작업을 인터럽트 하면서 종료
Exception in thread "main" java.util.concurrent.CancellationException
	ExecutorService executorService = Executors.newFixedThreadPool(3);
    Callable<String> hong = () -> {
        Thread.sleep(1000);
        return "hong";
    };
    Callable<String> jung = () -> {
        Thread.sleep(2000);
        return "jung";
    };
    Callable<String> wan = () -> {
        Thread.sleep(3000);
        return "wan";
    };
    List<Future<String>> futures = executorService.invokeAll(Arrays.asList(hong, jung, wan));
    for (Future<String> future : futures) {
        System.out.println(future.get());
    }invokeAll 메서드에 여러 작업들을 컬렉션으로 넘겨줄 수 있다.
	String answer = executorService.invokeAny(Arrays.asList(hong, jung, wan));
    System.out.println(answer);작업의 반환 값을 Future로 감싸지 않고 바로 반환
3개의 서버 존재 -> 동일 파일 존재 -> 파일 요청 시, 빠른 곳에서 하나만 받아도 됨