Java併發基礎(七)

1.fork/join示例

package com.zskj.concert.test.forkJoin;

import java.util.concurrent.RecursiveTask;

/**
 * @author cw
 * @date 2019/8/29
 */
public class ForkJoinSumCalculator extends RecursiveTask<Long> {
    private final long[] numbers;
    private final int start;
    private int end;
    public static final long THRESHOLD = 10L;

    public ForkJoinSumCalculator(long[] numbers) {
        this(numbers,0,numbers.length);
    }

    public ForkJoinSumCalculator(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 <=THRESHOLD){
            return computeSequentaily();
        }
        ForkJoinSumCalculator leftTask = new ForkJoinSumCalculator(numbers, start, start + length / 2);
        leftTask.fork();
        ForkJoinSumCalculator rightTask = new ForkJoinSumCalculator(numbers, start + length / 2, end);
        Long rightResult = rightTask.compute();
        Long leftResult = leftTask.join();
        return leftResult+rightResult;
    }
    //計算求和
    private Long computeSequentaily() {
        long sum = 0;
        for (int i = 0; i < end; i++) {
            sum += numbers[i];
        }
        return sum;
    }
}



//java8調用示例
    public static long forkJoinSum(long n){
        long[] numbers = LongStream.rangeClosed(1, n).toArray();
        ForkJoinSumCalculator task = new ForkJoinSumCalculator(numbers);
        return new ForkJoinPool().invoke(task);

    }

2使用分支/合併的最佳做法

  • 對於一個任務調用join方法會阻塞調用方,直到該任務做出結果
  • 不應該在ResucursiveTask內部使用ForkJoinPool的invoke方法。應該始終調用compute或者fork方法,只有順序代碼才應該用invoke來啓動計算。
  • 不應該認爲並行流以及分支/合框架在多個處理器上使用比順序計算快。

3.工作竊取技術

  • 問題:理想情況下,劃分並行任務時,應該讓每個任務用完全相同的時間完成,讓所有的CPU內核同樣繁忙。但是實際中,每個子任務所花的時間並不相同,
  • 分支/合併框架用一種稱爲工作竊取的技術來解決問題。
  • 工作原理:每個線程都爲分配給他的任務保存一個雙向隊列,每完成一個任務,就從隊列頭上取出下一個任務開始執行。有點可能早早完成,但是並沒有閒下來。而是隨機選取一個別的線程,從隊列的尾部拿取一個任務,直到所有的線程都結。
  • 一般來說,這種工作竊取算法用於池中的工作線程之間的重新分配和平衡任務。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章