기술 학습
JAVA 병렬 처리(Parallel Processing)와 ForkJoinPool 활용
EpicArts
2025. 2. 18. 19:14
1. 병렬 처리란?
병렬 처리(Parallel Processing)는 여러 개의 작업을 동시에 수행하여 프로그램의 성능을 극대화하는 기법입니다. 멀티코어 프로세서 환경에서는 병렬 처리를 활용하면 연산 속도를 크게 향상시킬 수 있습니다.
병렬 처리의 주요 특징:
- 작업을 여러 개의 코어에서 동시에 실행하여 성능 향상
- 멀티스레딩과 다르게 작업을 더 효율적으로 분배 가능
- Fork/Join 프레임워크를 활용하여 쉽게 구현 가능
2. Java에서 병렬 처리 구현 방법
2.1 parallelStream()을 활용한 병렬 처리
Java 8부터 컬렉션 프레임워크에서는 parallelStream()을 제공하여 간단하게 병렬 처리를 수행할 수 있습니다.
import java.util.Arrays;
import java.util.List;
public class ParallelStreamExample {
public static void main(String[] args) {
List<String> list = Arrays.asList("Apple", "Banana", "Cherry", "Date", "Elderberry");
list.parallelStream().forEach(System.out::println);
}
}
✅ parallelStream()을 활용하면 내부적으로 ForkJoinPool을 사용하여 병렬 실행됩니다.
2.2 ForkJoinPool을 활용한 병렬 처리
ForkJoinPool은 큰 작업을 작은 단위로 나누어 병렬로 실행할 수 있는 Java의 병렬 프레임워크입니다.
2.2.1 ForkJoinTask 정의하기
import java.util.concurrent.RecursiveTask;
public class ForkJoinSum extends RecursiveTask<Long> {
private final long[] numbers;
private final int start, end;
private static final int THRESHOLD = 1000;
public ForkJoinSum(long[] numbers, int start, int end) {
this.numbers = numbers;
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
if (end - start <= THRESHOLD) {
long sum = 0;
for (int i = start; i < end; i++) {
sum += numbers[i];
}
return sum;
}
int mid = (start + end) / 2;
ForkJoinSum leftTask = new ForkJoinSum(numbers, start, mid);
ForkJoinSum rightTask = new ForkJoinSum(numbers, mid, end);
leftTask.fork();
return rightTask.compute() + leftTask.join();
}
}
2.2.2 ForkJoinPool 실행하기
import java.util.concurrent.ForkJoinPool;
public class ForkJoinExample {
public static void main(String[] args) {
long[] numbers = new long[10_000];
for (int i = 0; i < numbers.length; i++) {
numbers[i] = i + 1;
}
ForkJoinPool pool = new ForkJoinPool();
ForkJoinSum task = new ForkJoinSum(numbers, 0, numbers.length);
long sum = pool.invoke(task);
System.out.println("합계: " + sum);
}
}
✅ ForkJoinPool은 작업을 자동으로 분할하고 병렬로 실행하여 성능을 최적화합니다.
3. CompletableFuture를 활용한 병렬 처리
CompletableFuture를 활용하면 여러 비동기 작업을 병렬로 실행하고 그 결과를 쉽게 병합할 수 있습니다.
import java.util.concurrent.CompletableFuture;
public class CompletableFutureParallelExample {
public static void main(String[] args) {
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
return 10;
});
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
return 20;
});
CompletableFuture<Integer> result = future1.thenCombine(future2, Integer::sum);
System.out.println("결과: " + result.join());
}
}
✅ thenCombine()을 활용하면 두 개의 비동기 작업을 병렬로 실행하고 결과를 합칠 수 있습니다.
4. 병렬 처리 성능 비교
방법사용 방식장점단점
parallelStream() | 컬렉션 데이터 병렬 처리 | 쉬운 사용법 | 작은 데이터에서는 성능 향상 미미 |
ForkJoinPool | 큰 작업을 나누어 병렬 처리 | 성능 최적화 가능 | 복잡한 코드 필요 |
CompletableFuture | 비동기 작업을 병렬 실행 | 병렬 처리 후 조합 가능 | 예외 처리 복잡 |
✅ 상황에 맞는 병렬 처리 방식을 선택하면 성능을 최적화할 수 있습니다.
5. 결론
이번 글에서는 Java에서 병렬 처리를 구현하는 다양한 방법을 살펴보았습니다. parallelStream(), ForkJoinPool, 그리고 CompletableFuture를 적절히 활용하면 대량의 데이터를 빠르게 처리할 수 있습니다.
다음 글에서는 Java의 멀티스레딩(Multithreading)과 동기화(Synchronization)에 대해 알아보겠습니다!