ForkJoinPool
ForkJoinPool이란?
Fork/Join 프레임워크 기반으로 작업을 병렬로 실행하고 작업을 더 작은 하위 작업으로 나누고, 최종 결과로 결합하는 ForkJoinTask를 위한 스레드 풀이다. (ExecutorService 구현)
Work stealing algo
작업을 마친 작업자 스레드가 다른 스레드에서 보류 중인 작업을 훔칠 수 있는 전략
- 병렬 실행에서는 작업이 여러 프로세서/코어로 나누어지는데 idle 상태가 되면 오버헤드 발생으로 다른 프로세서의 오버로드된 대기열(작업 대기열)에서 작업을 할당 받아야한다.
Fork/Join
Fork
작업을 분할/분해
- 작업을 스레드 풀의 작업 큐에 넣는다.
- 비동기 메서드
Join
풀 작업의 결과를 결합
- 동기 메서드
예제
public class Main {
public static void main(String[] args) {
long[] numbers = new long[1_000_000];
for (int i = 0; i < numbers.length; i++) {
numbers[i] = i;
}
ForkJoinPool pool = new ForkJoinPool();
Task task = new Task(numbers, 0, numbers.length);
long result = pool.invoke(task);
System.out.println("Sum: " + result);
pool.shutdown();
}
}
public class Task extends RecursiveTask<Long> {
private final long[] numbers;
private int start;
private int end;
public Task(long[] numbers, int start, int end) {
this.numbers = numbers;
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
int length = end - start;
if (length <= 100) {
long sum = 0;
for (int i = start; i < end; i++) {
sum += numbers[i];
}
return sum;
}
int middle = start + length / 2;
Task leftTask = new Task(numbers, start, middle);
Task rightTask = new Task(numbers, middle, end);
leftTask.**fork**();
Long rightResult = rightTask.compute();
Long leftResult = leftTask.**join**();
return leftResult + rightResult;
}
}