모던 자바인 액션 ch7 - 병렬 데이터 처리와 성능

김진욱·2022년 10월 10일
0

java

목록 보기
7/13
post-thumbnail

포크 조인 프레임 워크

  • fork() : 해당 작업을 쓰레드 풀의 작업 큐에 넣는다. - 비동기 메서드

  • join() : 해당 작업의 수행이 끝날 때까지 기다렸다가, 수행이 끝나면 그 결과를 반환한다. - 동기 메서드

  • 병렬화할 수 있는 작업을 재귀적으로 작은 작업으로 분할한 다음에 서브태스크 각각의 결과를 합쳐서 전체 결과를 만들도록 설계되었다.

  • 포크/조인 프레임 워크에서는 서브태스크를 스레드 풀(ForkJoinPool)의 작업자 스레드에 분산 할당하는 ExcutorService 인터페이스를 구현한다.

  • RecursiveTask, RecursiveAction

    • 두 클래스의 차이는 처리작업의 리턴 값 유무이다.
    • 리턴 값이 필요하면 RecursiveTas를 상속받아서 구현하면 되고 리턴 값이 필요없다면 RecursiveAction을 상속받아서 처리하면된다.
  • RecursiveTask

import java.util.List;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import java.util.stream.Collectors;

public class ForkJoin extends RecursiveTask<Integer> {

    private final List<Integer> numbers;

    public ForkJoin(List<Integer> numbers) {
        this.numbers = numbers;
    }


    @Override
    protected Integer compute() {
        if (numbers.size() <= 10) { // 배열의 크기가 10과 같거나 작으면 배열을 전부 더한 값을 반환한다.
            return numbers.stream().mapToInt(Integer::intValue).sum();
        }

        List<Integer> leftPart = numbers.subList(0, numbers.size() / 2);
        List<Integer> rightPart = numbers.subList(numbers.size() / 2, numbers.size());

        ForkJoin leftTask = new ForkJoin(leftPart);
        ForkJoin rightTask = new ForkJoin(rightPart);
        // Task를 배열 사이즈의 절반을 기준으로 2개로 나눈다.

        leftTask.fork(); // ForkJoinPool의 다른 스레드로 새로 생성한 태스크를 비동기로 실행

        return rightTask.compute() + leftTask.join();
    }

  • 작업 훔치기
    • 스레드마다 자신에게 할당된 작업이 끝나는 시점은 전부 다르다. 만약 한 스레드가 작업이 빨리 끝났다면 유휴 상태로 변경되는 것이 아니라 다른 스레드 큐의 꼬리에서 작업을 훔쳐온다.

0개의 댓글

관련 채용 정보