ForkJoinPool — ForkJoinTask 실행용 ExecutorService
ForkJoinPool — ForkJoinTask 실행용 ExecutorService
ForkJoinPool은 ForkJoinTask를 실행하기 위한 ExecutorService예요. work-stealing을 사용해, 대부분의 태스크가 하위 태스크를 생성하는 분할 정복 작업을 효율적으로 처리하는 풀이에요.
본문
개념 이해하기
ForkJoinPool은 ForkJoinTask를 실행하기 위한 ExecutorService이며, non-ForkJoinTask 클라이언트의 제출 진입점이자 관리·모니터링 연산을 제공해요.
public class ForkJoinPool
extends AbstractExecutorService
implements Executor, ExecutorService, AutoCloseable
다른 ExecutorService와 달리 work-stealing을 사용해요 — 풀의 모든 스레드가 풀에 제출되고/또는 다른 활성 태스크가 만든 태스크를 찾아 실행해요. 대부분의 ForkJoinTask처럼 대부분의 태스크가 하위 태스크를 생성할 때, 그리고 외부 클라이언트가 많은 작은 태스크를 제출할 때 효율적이에요. 모든 워커 스레드는 Thread.isDaemon()이 true로 초기화돼요.
commonPool
static commonPool()은 대부분의 애플리케이션에 적합해요. 명시적으로 지정된 풀에 제출되지 않은 모든 ForkJoinTask가 사용해요. common pool을 쓰면 비사용 기간에 스레드가 서서히 회수되고 재사용 시 복원돼 자원 사용을 줄여요.
실행 메서드 요약
| 호출 위치 | non-fork/join 클라이언트 | fork/join 계산 내부 |
|---|---|---|
| 비동기 실행 정렬 | execute(ForkJoinTask) |
ForkJoinTask.fork() |
| 결과 대기·획득 | invoke(ForkJoinTask) |
ForkJoinTask.invoke() |
| 실행 정렬 + Future 획득 | submit(ForkJoinTask) |
ForkJoinTask.fork() (ForkJoinTask는 Future) |
common pool의 생성 매개변수는 시스템 프로퍼티로 제어할 수 있어요: java.util.concurrent.ForkJoinPool.common.parallelism, ...common.threadFactory, ...common.exceptionHandler, ...common.maximumSpares (기본 256).
구현 노트: 이 구현은 최대 실행 스레드 수를 32767로 제한해요. 초과하면 IllegalArgumentException. 또한 풀이 종료됐거나 내부 자원이 고갈됐을 때만 제출된 태스크를 거부(RejectedExecutionException)해요.
생성자
public ForkJoinPool() — Runtime.availableProcessors()와 같은 병렬 수준, 그 외 기본값.
SecurityException
public ForkJoinPool(int parallelism) — 지정된 병렬 수준.
IllegalArgumentException,SecurityException
public ForkJoinPool(int parallelism, ForkJoinPool.ForkJoinWorkerThreadFactory factory, Thread.UncaughtExceptionHandler handler, boolean asyncMode) — 지정된 매개변수. asyncMode가 true면 절대 join되지 않는 forked 태스크에 대해 로컬 FIFO 스케줄링 모드를 설정해요(워커 스레드가 이벤트 스타일 비동기 태스크만 처리하는 앱에 더 적합).
IllegalArgumentException,NullPointerException,SecurityException
public ForkJoinPool(int parallelism, ...Factory, UncaughtExceptionHandler, boolean asyncMode, int corePoolSize, int maximumPoolSize, int minimumRunnable, Predicate<? super ForkJoinPool> saturate, long keepAliveTime, TimeUnit unit) — 모든 매개변수를 지정하는 전체 생성자. (JDK 9+)
corePoolSize— 유지할 스레드 수(기본 병렬 수준 값),maximumPoolSize— 최대 스레드 수,minimumRunnable— join/ManagedBlocker에 의해 블로킹되지 않은 핵심 스레드의 최소 수,saturate— 최대 스레드 초과 생성 시도 시 호출되는 술어,keepAliveTime— 마지막 사용 이후 종료까지의 시간 (기본60, TimeUnit.SECONDS)
정적·공통 메서드
public static ForkJoinPool commonPool() — common pool 인스턴스를 반환해요. 정적으로 구성되며 shutdown()/shutdownNow()에 영향받지 않아요. System.exit 시 자동 종료. 프로그램 종료 전 비동기 처리를 기다려야 하면 commonPool().awaitQuiescence 호출. (JDK 1.8+)
public static int getCommonPoolParallelism() — common pool의 목표 병렬 수준. (JDK 1.8+)
public static void managedBlock(ForkJoinPool.ManagedBlocker blocker) throws InterruptedException — 주어진 가능한 블로킹 태스크를 실행해요. ForkJoinPool에서 실행 중일 때 현재 스레드가 blocker.block()에 블로킹되는 동안 충분한 병렬성을 위해 스페어 스레드를 활성화할 수 있어요. blocker.isReleasable()/blocker.block()을 true가 될 때까지 반복해요.
실행 메서드
public <T> T invoke(ForkJoinTask<T> task) — 태스크를 수행하고 완료 시 결과를 반환해요. 비검사 예외/오류는 재던져져요.
NullPointerException,RejectedExecutionException
public void execute(ForkJoinTask<?> task) — (비동기) 실행을 정렬해요.
NullPointerException,RejectedExecutionException
public <T> ForkJoinTask<T> submit(ForkJoinTask<T> task) — 실행을 제출하고 태스크를 반환해요. 대기 중 결과는 태스크 자체가 Future예요.
public <T> ForkJoinTask<T> externalSubmit(ForkJoinTask<T> task) — non-ForkJoinTask 클라이언트처럼 제출해요. 풀의 스레드에서 호출해도 스케줄링 큐에 추가돼요. (JDK 20+)
public <T> ForkJoinTask<T> lazySubmit(ForkJoinTask<T> task) — 활성 스레드가 없어도 결국 실행됨을 보장하지 않고 제출해요. 경합·오버헤드를 줄일 수 있어요. (JDK 19+)
submit(Callable), submit(Runnable, result), submit(Runnable), invokeAll(Collection)도 제공돼요.
관리·상태
public int setParallelism(int size) — 병렬 수준을 변경하고 이전 값을 반환해요. (JDK 19+). IllegalArgumentException, UnsupportedOperationException (commonPool이 프로퍼티로 설정된 경우), SecurityException.
public ForkJoinPool.ForkJoinWorkerThreadFactory getFactory(), public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() — 팩토리/핸들러 반환.
public int getParallelism() — 목표 병렬 수준.
public int getPoolSize() — 시작됐지만 종료되지 않은 워커 스레드 수.
public boolean getAsyncMode() — async 모드 여부.
public int getRunningThreadCount() — join 태스크 대기나 다른 관리 동기화에 블로킹되지 않은 워커 수 추정치.
public int getActiveThreadCount() — 현재 훔치거나 실행 중인 스레드 수 추정치.
public boolean isQuiescent() — 모든 워커가 유휴면 true. 보수적.
public long getStealCount() — 제출자 아닌 다른 스레드가 실행한 완료 태스크 수 추정치.
public long getQueuedTaskCount() / public int getQueuedSubmissionCount() / public boolean hasQueuedSubmissions() — 큐된 태스크/제출 수.
종료
public void shutdown() — 질서 있는 정리. commonPool()이면 실행 상태에 영향 없음. SecurityException.
public List<Runnable> shutdownNow() — 모든 태스크 취소·중지 시도. 항상 빈 목록을 반환해요(태스크 의존성 때문에 기존·미실행 태스크를 모두 취소하므로). commonPool()이면 영향 없음.
public boolean isTerminated(), public boolean isTerminating(), public boolean isShutdown() — 상태 질의.
public boolean awaitTermination(long timeout, TimeUnit unit) — 종료 대기. common pool엔 awaitQuiescence와 동등하되 항상 false 반환.
public boolean awaitQuiescence(long timeout, TimeUnit unit) — 풀이 quiescent되거나 타임아웃까지 대기하거나 태스크 수행을 지원.
public void close() — commonPool()이 아니면 질서 있는 종료 후 완료·종료까지 대기. (JDK 19+)
public String toString() — 풀 상태(실행 상태, 병렬 수준, 워커·태스크 수)를 식별하는 문자열.