0Pricing
Java Academy · 강의

Future와 오류 처리

시간 제한과 함께 Future.get을 사용하고 ExecutionException을 처리하며 실행 중인 작업을 취소합니다.

Future와 오류 처리은(는) CoddyKit의 무료 Java Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Java Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

Future란 무엇인가

Future<V>는 비동기 계산에서 아직 완료되지 않은 결과를 나타냅니다. 완료 여부 확인, 결과 대기, 오류 처리를 위한 메서드를 제공합니다.

import java.util.concurrent.*;

ExecutorService pool = Executors.newFixedThreadPool(2);
Future<Integer> future = pool.submit(() -> {
    Thread.sleep(1000);
    return 42;
});

System.out.println("Is done? " + future.isDone()); // false
Integer result = future.get(); // blocks
System.out.println("Result: " + result); // 42
pool.shutdown();

시간 제한이 있는 future.get()

무기한 멈추는 것을 방지하려면 항상 시간 제한이 있는 형식을 우선 사용합니다.

try {
    Integer result = future.get(5, TimeUnit.SECONDS);
    System.out.println(result);
} catch (TimeoutException e) {
    System.out.println("Timed out");
    future.cancel(true); // interrupt the task
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
} catch (ExecutionException e) {
    System.out.println("Task threw: " + e.getCause());
}

ExecutionException

작업에서 예외가 발생하면 future.get()은 해당 예외를 ExecutionException으로 감쌉니다. getCause()로 원인을 꺼냅니다.

Future<String> failing = pool.submit(() -> {
    throw new IllegalArgumentException("bad input");
});

try {
    failing.get();
} catch (ExecutionException e) {
    Throwable cause = e.getCause();
    System.out.println(cause.getClass().getSimpleName()); // IllegalArgumentException
    System.out.println(cause.getMessage()); // bad input
}

Future 취소

cancel(mayInterruptIfRunning)은 작업을 취소하려고 시도합니다. 성공하면 true를 반환합니다. mayInterruptIfRunning이 true이면 실행 중인 스레드에 인터럽트가 전송됩니다.

Future<String> f = pool.submit(() -> {
    try {
        Thread.sleep(10_000); // long task
        return "done";
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        return "interrupted";
    }
});

boolean cancelled = f.cancel(true); // send interrupt
System.out.println("Cancelled: " + cancelled); // true
System.out.println("Is cancelled: " + f.isCancelled()); // true

isCancelled와 isDone 비교

isDone()은 작업이 정상적으로 완료되었거나, 예외가 발생했거나, 취소된 경우 true를 반환합니다. isCancelled()은 취소된 경우에만 true를 반환합니다.

// After cancel:
System.out.println(f.isDone());       // true
System.out.println(f.isCancelled()); // true

// After normal completion:
Future<Integer> done = pool.submit(() -> 5);
done.get(); // wait
System.out.println(done.isDone());       // true
System.out.println(done.isCancelled()); // false

사용 가능한 첫 결과를 위한 CompletionService

ExecutorCompletionService는 풀을 감싸고 다음으로 완료된 Future를 가져오는 take() 메서드를 제공합니다. 제출 순서가 아니라 완료 순서로 가져옵니다.

ExecutorCompletionService<Integer> cs =
    new ExecutorCompletionService<>(pool);

for (int i = 0; i < 5; i++) {
    final int delay = 5 - i; // submit fastest last
    cs.submit(() -> { Thread.sleep(delay * 100); return delay; });
}

for (int i = 0; i < 5; i++) {
    Future<Integer> f = cs.take(); // next completed
    System.out.println(f.get());
}

여러 Future의 안전한 처리

많은 Future에서 결과를 수집할 때는 각 Future를 순회하면서 개별적으로 예외를 처리합니다.

List<Future<String>> futures = new ArrayList<>();
for (int i = 0; i < 5; i++) {
    final int id = i;
    futures.add(pool.submit(() ->
        id % 2 == 0 ? "ok_" + id : (() -> { throw new RuntimeException("fail_"+id); }).get()
    ));
}

for (Future<String> f : futures) {
    try {
        System.out.println(f.get());
    } catch (ExecutionException e) {
        System.out.println("Error: " + e.getCause().getMessage());
    }
}

풀 종료 후 Future.get()

shutdown() 후에 작업을 제출하면 RejectedExecutionException이 발생합니다. 하지만 종료 전에 제출한 Future는 종료 후에도 가져올 수 있습니다.

ExecutorService pool2 = Executors.newFixedThreadPool(2);
Future<Integer> f = pool2.submit(() -> 99);
pool2.shutdown(); // no new tasks

// Still valid — task was submitted before shutdown:
System.out.println(f.get()); // 99

try {
    pool2.submit(() -> 0); // throws!
} catch (RejectedExecutionException e) {
    System.out.println("Pool shut down");
}

FutureTask: 수동 비동기 결과

FutureTask<V>는 Runnable과 Future<V>를 모두 구현합니다. ExecutorService 없이 Future가 필요할 때 유용합니다.

FutureTask<String> task = new FutureTask<>(() -> "computed");
new Thread(task).start(); // run in any thread
System.out.println(task.get()); // computed

Future를 사용한 재시도 패턴

future.get() 주위에 간단한 재시도 로직을 구현합니다.

Future<String> future = pool.submit(() -> {
    if (Math.random() < 0.7) throw new RuntimeException("transient error");
    return "success";
});

for (int attempt = 0; attempt < 3; attempt++) {
    try {
        System.out.println(future.get());
        break;
    } catch (ExecutionException e) {
        System.out.println("Attempt " + (attempt+1) + " failed");
        if (attempt == 2) throw e;
        future = pool.submit(() -> "retry"); // resubmit
    }
}

Future의 제한 사항

java.util.concurrent.Future에는 다음과 같은 제한 사항이 있습니다.

  • 콜백이 없으므로 get()에서 블로킹해야 합니다.
  • 변환을 연결할 수 없습니다.
  • 여러 Future를 결합할 수 없습니다.

반응형 비차단 조합이 필요하다면 다음 과정에서 다루는 CompletableFuture를 사용합니다.

확인 문제

작업에서 예외가 발생했습니다. future.get()을 호출하면 어떤 예외가 발생합니까?

복습: Future와 오류 처리

핵심 내용은 다음과 같습니다.

  • future.get()은 블로킹되므로 항상 시간 제한이 있는 형식을 사용합니다.
  • ExecutionException은 작업의 예외를 감싸며, getCause()로 원인을 꺼냅니다.
  • cancel(true)은 인터럽트를 전송하고, isDone/isCancelled로 상태를 확인합니다.
  • ExecutorCompletionService.take()은 완료 순서대로 Future를 가져옵니다.
  • FutureTask는 Runnable과 Future를 모두 구현합니다.

자주 묻는 질문

“Future와 오류 처리” 강의는 무료인가요?

네 — “Future와 오류 처리” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Java Academy 강의 전체를 잠금 해제할 수 있습니다. Java Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“Future와 오류 처리”에서 뭘 배우나요?

시간 제한과 함께 Future.get을 사용하고 ExecutionException을 처리하며 실행 중인 작업을 취소합니다. 브라우저에서 직접 실행하는 실습 코드로 Java Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Java Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Java Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“Future와 오류 처리” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Java Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Java Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. ExecutorService와 스레드 풀 유형
  2. 작업 제출: Runnable과 Callable
  3. Future와 오류 처리
  4. 반복 작업을 위한 ScheduledExecutorService
← Java Academy(으)로 돌아가기