스레드풀의 작업이 완료될 때까지 기다리는 방법은 무엇인가요?
_____A: 스레드풀에서 작업이 완료될 때까지 기다리는 일반적인 방법은 다음과 같습니다.
1. ExecutorService의 `shutdown()`과 `awaitTermination()` 사용하기
- 작업 제출이 완료된 후 `shutdown()` 메서드를 호출하여 더 이상 작업을 받지 않도록 스레드풀을 종료 시도합니다.
- 이후 `awaitTermination(long timeout, TimeUnit unit)` 메서드를 호출하면 지정한 시간 동안 모든 작업이 완료되기를 대기합니다.
- 예시:
```java
ExecutorService executor = Executors.newFixedThreadPool(4);
// 작업 제출
executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow(); // 시간이 다되었으면 강제 종료
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}
```
- 이 방법은 스레드풀이 종료되고, 제출된 모든 작업이 끝날 때까지 기다립니다.
2. `Future.get()` 이용하기
- 작업을 제출할 때 `submit()` 메서드를 사용하여 `Future` 객체를 받으면, 각 `Future`의 `get()` 메서드를 호출하여 해당 작업의 완료까지 대기할 수 있습니다.
- 예시:
```java
List
for (Runnable task : tasks) {
futures.add(executor.submit(task));
}
for (Future> future : futures) {
future.get(); // 작업 완료 시까지 대기
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
```
- 모든 `Future.get()` 호출이 종료되면, 모든 작업이 완료된 상태입니다.
3. CountDownLatch 같은 동기화 도구 사용하기
- 여러 작업의 완료 시점을 알아야 한다면, `CountDownLatch`를 사용하여 각 작업이 끝날 때마다 `countDown()`을 호출하도록 한 후, 메인 스레드에서 `await()`로 대기합니다.
- 예시:
```java
int taskCount = tasks.size();
CountDownLatch latch = new CountDownLatch(taskCount);
for (Runnable task : tasks) {
executor.submit(() -> {
try {
task.run();
} finally {
latch.countDown();
}
});
}
latch.await(); // 모든 작업 완료 시까지 대기
```
요약:
- 모든 작업 제출이 끝난 후 `shutdown()` + `awaitTermination()`으로 스레드풀 전체 종료를 기다린다.
- 또는 각 작업의 `Future.get()`을 호출하여 작업별 완료를 명시적으로 기다린다.
- 더 정교한 동기화가 필요하면 `CountDownLatch` 등 별도의 동기화 도구를 사용한다.
이들 방법을 통해 스레드풀 내 모든 작업이 완료될 때까지 효과적으로 기다릴 수 있습니다.
스레드풀은 미리 생성된 스레드의 집합으로, 작업이 들어오면 대기 중인 스레드가 이를 처리합니다.
이로 인해 스레드를 매번 생성하고 소멸시키는 오버헤드를 줄일 수 있습니다.
그러나 스레드풀에서 수행되는 작업이 완료될 때까지 기다려야 하는 경우가 종종 있습니다.
이때 사용할 수 있는 여러 가지 방법이 있습니다.
1. `Future` 객체 사용하기 Java의 `ExecutorService`를 사용하여 스레드풀에서 작업을 제출할 때, `submit()` 메서드는 `Future` 객체를 반환합니다.
이 객체는 작업의 결과를 나타내며, `get()` 메서드를 호출하여 작업이 완료될 때까지 기다릴 수 있습니다.
```java ExecutorService executor = Executors.newFixedThreadPool(
10); Future
2. `CountDownLatch` 사용하기 `CountDownLatch`는 특정 작업이 완료될 때까지 대기할 수 있는 동기화 도구입니다.
여러 개의 작업이 있을 때, 각 작업이 완료될 때마다 카운트를 감소시키고, 카운트가 0이 될 때까지 대기할 수 있습니다.
```java ExecutorService executor = Executors.newFixedThreadPool(
10); CountDownLatch latch = new CountDownLatch(numberOfTasks); for (int i = 0; i < numberOfTasks; i++) { executor.submit(() -> { try { // 작업 수행 } finally { latch.countDown(); // 작업 완료 시 카운트 감소 } }); } latch.await(); // 모든 작업이 완료될 때까지 대기 executor.shutdown(); ```
3. `CompletionService` 사용하기 `CompletionService`는 작업이 완료되는 대로 결과를 가져올 수 있는 구조입니다.
`ExecutorCompletionService`를 사용하면, 작업이 완료될 때마다 결과를 가져올 수 있습니다.
```java ExecutorService executor = Executors.newFixedThreadPool(
10); CompletionService
4. `ForkJoinPool` 사용하기 Java 7부터 도입된 `ForkJoinPool`은 작업을 분할하고 병렬로 처리하는 데 최적화된 스레드풀입니다.
`ForkJoinTask`를 사용하여 작업을 제출하고, `invokeAll()` 메서드를 통해 모든 작업이 완료될 때까지 대기할 수 있습니다.
```java ForkJoinPool forkJoinPool = new ForkJoinPool(); List
`Future` 객체를 사용하면 간단하게 작업 결과를 얻을 수 있고, `CountDownLatch`는 여러 작업을 동시에 관리할 때 유용합니다.
`CompletionService`는 작업이 완료되는 대로 결과를 처리할 수 있는 장점이 있으며, `ForkJoinPool`은 대규모 병렬 처리에 적합합니다.
상황에 맞는 방법을 선택하여 효율적으로 스레드풀의 작업을 관리하세요.
작성자:
박시현 [비회원]
| 작성일자: 1년 전
2024-11-21 22:51:34
조회수: 160 | 댓글: 0 | 좋아요: 0 | 싫어요: 0
조회수: 160 | 댓글: 0 | 좋아요: 0 | 싫어요: 0
내용이 부정확하다면 싫어요를 클릭해주세요.