자바 병발 중인 포크/Join 프레임 워 크 메커니즘 상세 설명
포크/Join 프레임 워 크 는 JDk 7 에 도 입 된 스 레 드 풀 로 하나의 큰 임 무 를 여러 개의 작은 임무 로 분해 하여 병행 하여 수행 하 며,최종 적 으로 모든 작은 임무 결 과 를 모 아 큰 임무 결 과 를 얻 는 특수 임무 입 니 다.이름 을 통 해 알 수 있 듯 이 프레임 워 크 는 주로 Fork 와 Join 두 단계 로 나 뉘 는데 첫 번 째 단 계 는 Fork 는 하나의 큰 임 무 를 여러 개의 하위 임무 로 나 누 어 병행 하 는 것 이 고 두 번 째 단 계 는 Join 은 이 하위 임무 의 모든 수행 결 과 를 합 쳐 큰 임 무 를 얻 은 결과 이다.
여기 서 주요 절 차 를 발견 하기 어렵 지 않다.먼저 하나의 임무 가 충분 한 지 판단 하고 임무 가 충분 하면 직접 계산한다.그렇지 않 으 면 몇 개의 더 작은 임무 로 나 누 어 각각 계산한다.이 과정 은 일련의 작은 임무 로 반복 적 으로 나 눌 수 있다.포크/Join 프레임 워 크 는 분할 통치하 다 을 기반 으로 한 알고리즘 으로 큰 임 무 를 나 누 어 여러 개의 독립 된 작은 임 무 를 수행 한 다음 에 이 작은 임 무 를 병행 하여 작은 임 무 를 합 친 결과 큰 임무 의 최종 결 과 를 얻 고 병행 계산 을 통 해 효율 을 높 인 다.
Fork/Join 프레임 워 크 사용 예시
다음은 계산 목록 에 있 는 모든 요소 의 총 화 를 예 로 들 어 Fork/Join 프레임 워 크 가 어떻게 사용 되 는 지 살 펴 보 겠 습 니 다.전체적인 사 고 는 이 목록 을 여러 하위 목록 으로 나 눈 다음 에 모든 하위 목록 의 요 소 를 구 한 다음 에 우 리 는 이 값 의 총 화 를 계산 하면 원시 목록 의 합 을 얻 을 수 있 습 니 다.포크/Join 프레임 워 크 에서 포크 Jointask 를 정의 하여 포크/Join 작업 을 표시 합 니 다.포크(),join()등 작업 을 제공 합 니 다.일반적인 상황 에서 저 희 는 이 포크 Jointask 클래스 를 직접 계승 하지 않 고 프레임 워 크 로 제공 하 는 두 개의 포크 Jointask 하위 클래스 를 사용 합 니 다.
/**
* @author mghio
* @since 2021-07-25
*/
public class SumTask extends RecursiveTask<Long> {
private static final int SEQUENTIAL_THRESHOLD = 50;
private final List<Long> data;
public SumTask(List<Long> data) {
this.data = data;
}
@Override
protected Long compute() {
if (data.size() <= SEQUENTIAL_THRESHOLD) {
long sum = computeSumDirectly();
System.out.format("Sum of %s: %d
", data.toString(), sum);
return sum;
} else {
int mid = data.size() / 2;
SumTask firstSubtask = new SumTask(data.subList(0, mid));
SumTask secondSubtask = new SumTask(data.subList(mid, data.size()));
//
firstSubtask.fork();
secondSubtask.fork();
// ,
long firstSubTaskResult = firstSubtask.join();
long secondSubTaskResult = secondSubtask.join();
return firstSubTaskResult + secondSubTaskResult;
}
}
private long computeSumDirectly() {
long sum = 0;
for (Long l : data) {
sum += l;
}
return sum;
}
public static void main(String[] args) {
Random random = new Random();
List<Long> data = random
.longs(1_000, 1, 100)
.boxed()
.collect(Collectors.toList());
ForkJoinPool pool = new ForkJoinPool();
SumTask task = new SumTask(data);
pool.invoke(task);
System.out.println("Sum: " + pool.invoke(task));
}
}
목록 크기 가 SEQUENTIAL 보다 작 을 때THRESHOLD 변수의 값(한도 값)을 작은 작업 으로 보고 구 와 목록 요소 의 결 과 를 직접 계산 합 니 다.그렇지 않 으 면 다시 작은 작업 으로 나 누 어 실행 결 과 는 다음 과 같 습 니 다.이 예제 코드 를 통 해 알 수 있 듯 이 Fork/Join 프레임 워 크 에서 ForkJoinTask 작업 과 일반적인 일반적인 작업 의 주요 차이 점 은 다음 과 같다.ForkJoinTask 는 추상 적 인 방법 coptute()를 실현 하여 계산 논 리 를 정의 해 야 한다.이 방법 에서 일반적으로 통용 되 는 실현 템 플 릿 은 먼저 현재 작업 이 작은 작업 인지 아 닌 지 를 판단 하고 만약 그렇다면 임 무 를 수행 해 야 한다.작은 작업 이 아니라면 두 개의 하위 작업 으로 나 누 어 진 다음 각 하위 작업 이 fork()방법 을 호출 할 때 compute()방법 에 다시 들 어가 현재 작업 을 하위 작업 으로 나 눌 필요 가 있 는 지 확인 합 니 다.작은 작업 이 라면 현재 임 무 를 수행 하고 결 과 를 되 돌려 줍 니 다.그렇지 않 으 면 계속 분할 합 니 다.마지막 으로 join()방법 을 호출 하여 모든 하위 작업 이 완 료 될 때 까지 기다 리 고 실행 결 과 를 얻 습 니 다.의사 코드 는 다음 과 같 습 니 다:
if (problem is small) {
directly solve problem.
} else {
Step 1. split problem into independent parts.
Step 2. fork new subtasks to solve each part.
Step 3. join all subtasks.
Step 4. compose result from subresults.
}
포크/Join 프레임 디자인포크/Join 프레임 워 크 의 핵심 사상 은 하나의 큰 임 무 를 여러 개의 작은 임무 로 나 눈 다음 에 모든 작은 임무 의 결 과 를 모 아 큰 임무 의 결 과 를 얻 는 것 입 니 다.만약 에 이런 프레임 워 크 를 설계 하 라 고 하면 어떻게 실현 할 것 입 니까?생각해 보 세 요)포크/Join 프레임 워 크 의 전체 절 차 는 그 이름 에서 보 듯 이 두 단계 로 나 뉜 다.
병발 한 이상 컴퓨터 의 성능 을 최대한 압착 해 야 한다.이런 장면 에 대해 병발 대사 Doug Lea 은 작업 절취 알고리즘 처 리 를 사 용 했 고 작업 도 난 알고리즘 을 사용 한 후에 자신의 대열 에서 임 무 를 수행 하 는 스 레 드 를 먼저 완성 하면 다른 스 레 드 의 대열 에서'하나의 임 무 를 훔 쳐 서 집행 한다.하하,한 측 이 어렵 고 팔방 이 지원 한다.그러나 이 스 레 드 와 대기 열의 보유 스 레 드 는 같은 대기 열 에 동시에 접근 하기 때문에 훔 친 작업 의 스 레 드 와 도 둑 맞 은 작업 의 스 레 드 간 의 경쟁 을 줄 이기 위해 ForkJoin 은 쌍 단 대기 열 이라는 데이터 구 조 를 선택 하면 이러한 규칙 에 따라 임 무 를 수행 할 수 있 습 니 다.도 둑 맞 은 작업 의 스 레 드 는 항상 대기 열 머리 에서 임 무 를 가 져 오고 수행 할 수 있 습 니 다.작업 을 훔 치 는 스 레 드 는 대기 열 끝 에서 작업 을 수행 하 는 데 사 용 됩 니 다.이 알고리즘 은 대부분 상황 에서 다 중 스 레 드 를 충분히 이용 하여 병행 계산 을 할 수 있 지만 양 단 대기 열 에 하나의 임무 만 있 는 등 극단 적 인 상황 에서 어느 정도 경쟁 이 존재 할 수 있 습 니 다.
포크/Join 프레임 워 크 실현 원리
Fork/Join 프레임 워 크 의 실현 핵심 은 ForkJoinPool 류 입 니 다.이 유형의 중요 한 구성 부분 은 ForkJoinTask 배열 과 ForkJoinWorkerThread 배열 입 니 다.그 중에서 ForkJoinTask 배열 은 프레임 워 크 사용자 가 ForkJoinPool 에 제출 한 임 무 를 저장 하고 ForkJoinWorkerThread 배열 은 이 임 무 를 수행 합 니 다.작업 은 다음 과 같은 네 가지 상태 가 있 습 니 다.
NORMAL 이 완료 되 었 습 니 다.
CANCELLED 가 취소 되 었 습 니 다.
SIGNAL 신호
예외 적 으로 이상 발생
다음은 이 두 가지 핵심 방법의 실현 원 리 를 살 펴 보 겠 습 니 다.먼저 ForkJointask 의 fork()방법 을 살 펴 보 겠 습 니 다.소스 코드 는 다음 과 같 습 니 다.
방법 은 ForkJoinWorkerThread 형식의 스 레 드 에 대해 먼저 ForkJoinWorkerThread 의 work Queue 의 push()방법 으로 이 작업 을 비동기 적 으로 수행 한 다음 결 과 를 되 돌려 줍 니 다.ForkJoinPool 의 push()방법 을 계속 따라 갑 니 다.원본 코드 는 다음 과 같 습 니 다.
방법 은 현재 작업 을 ForkJoinTask 작업 대기 열 배열 에 추가 한 다음 ForkJoinPool 의 signal Work 방법 으로 작업 스 레 드 를 만 들 거나 깨 워 서 이 작업 을 수행 합 니 다.그리고 ForkJointask 의 join()방법 을 살 펴 보 겠 습 니 다.방법 원본 은 다음 과 같 습 니 다.
방법 은 먼저 doJoin()방법 을 호출 했 습 니 다.이 방법 은 현재 작업 의 상 태 를 되 돌려 주 고 돌아 오 는 작업 상태 에 따라 다른 처 리 를 합 니 다.
방법 은 우선 현재 작업 상태 가 이미 완성 되 었 는 지 판단 하고,실행 이 완료 되면 바로 작업 상태 로 돌아 갑 니 다.수행 이 완료 되 지 않 으 면 작업 배열(work Queue)에서 작업 을 꺼 내 수행 하고,작업 수행 이 완료 되면 작업 상 태 를 NORMAL 로 설정 하 며,이상 이 발생 하면 이상 을 기록 하고 작업 상 태 를 EXCEPTIONAL(doExec()방법 에서)로 설정 합 니 다.
총결산
본 고 는 자바 병발 프레임 워 크 의 포크/Join 프레임 워 크 의 기본 원리 와 그 가 사용 하 는 작업 절취 알고리즘(work-stealing),디자인 방식 과 부분 실현 소스 코드 를 소개 한다.Fork/Join 프레임 워 크 는 JDK 의 공식 표준 라 이브 러 리 에서 도 적용 된다.예 를 들 어 JDK 1.8+표준 라 이브 러 리 가 제공 하 는 Arrays.parallelsert(array)는 병렬 정렬 을 할 수 있 습 니 다.그 원 리 는 내부 에서 Fork/Join 프레임 워 크 를 통 해 큰 배열 을 병렬 정렬 하면 정렬 의 속 도 를 높 일 수 있 고 집합 중의 Collection.parallels트림()의 바 텀 도 Fork/Join 프레임 워 크 를 바탕 으로 이 루어 집 니 다.마지막 으로 작은 작업 의 한도 값 을 정의 하 는 것 은 테스트 검증 을 통 해 합 리 적 으로 제시 하고 프로그램 이 가장 좋 은 성능 을 얻 을 수 있 도록 하 는 것 이다.
자바 병발 중인 포크/조 인 트 프레임 워 크 메커니즘 에 대한 자세 한 설명 은 여기까지 입 니 다.자바 포크/조 인 트 프레임 워 크 에 관 한 더 많은 내용 은 저희 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 부탁드립니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.