JAVA併發編程梳理與學習三(ForkJoin)

一、ForkJoin說明
ForkJoin是jdk1.7增加的併發工具類,可以解決分而治之的問題,就是把一個任務分爲若干小任務,併發的去處理,最後再把處理結果合併起來,從而達到提高速度的目的。使用時要保證每個小任務互不干擾、相互獨立且結構和主任務相同,用遞歸的方法解決這些小任務,最終合併到一起
在這裏插入圖片描述
二、ForkJoin使用
1.首先創建ForkJoinPool,ForkJoinPool可以理解爲一個線程池,裏面維護的線程數一般爲cpu核數,不斷的執行拆分的任務,並且還會工作竊取,就是自己的活要是幹完了空閒了,會獲取其他線程的task,從而達到空閒率,提高效率。
ForkJoinPool pool=new ForkJoinPool()
**2.創建ForkJoin任務,**去交給ForkJoinPool執行,一般我們會繼承ForkjoinTask的子類RecursiveAction或者RecursiveTask
(1)RecursiveAction沒有返回值的任務
(2)RecursiveTask用於有返回值的任務
然後要實現裏面的compute方法,compute方法裏面先要判斷是否滿足我們拆分的最小任務條件,如果滿足就執行處理方法並把結果交給上一級的任務(就是拆分出來現在小任務的那個任務);如果不滿足調用fork或者invokeAll(遞歸)再去拆分;最後通過join(阻塞方法)彙總
3.執行ForkJoinPool的submit 或 invoke第一次拆分提交
(1)submit是異步執行
(2)invoke是同步執行,必須等到任務完成,纔會執行下面代碼
下面是個具體實例計算1~40000的值

public class ForkJoinTest extends RecursiveTask<Integer> {

    private int[] arrys;//存放相加數據的數組
    private int THRESHOLD=400;//定義閾值,拆成每個數組400個元素
    private int startIndex;
    private int endIndex;


    public ForkJoinTest(int[] arrys,int startIndex,int endIndex){
       this.arrys=arrys;
       this.startIndex=startIndex;
        this.endIndex=endIndex;
    }


    @Override
    protected Integer compute() {
        if(endIndex-startIndex<=THRESHOLD){//判斷拆分數組長度是否在閾值內
            int count=0;
            for(int i=startIndex;i<=endIndex;i++){
                count+=arrys[i];
            }
            return count;//將結果交給上一級task

        }else{
            int mid=(startIndex+endIndex)/2;//找中值繼續拆分
            ForkJoinTest leftForkJoin=new ForkJoinTest(arrys,startIndex,mid);
            ForkJoinTest rightForkJoin=new ForkJoinTest(arrys,mid+1,endIndex);
            leftForkJoin.fork();
            rightForkJoin.fork();  //或者用invokeAll(leftForkJoin,rightForkJoin)
            return leftForkJoin.join()+rightForkJoin.join();//合併所有子任務值
        }
    }

    public static void main(String[] args){
        long timeStart= System.currentTimeMillis();
        int[] arrys=new int[40000];
        for(int i=0;i<40000;i++){
            arrys[i]=i;
        }

        ForkJoinPool pool=new ForkJoinPool();
        ForkJoinTest forkJoinTest=new ForkJoinTest(arrys,0,arrys.length-1);
        pool.invoke(forkJoinTest);
        System.out.println(System.currentTimeMillis()-timeStart+"count:"+forkJoinTest.join());

    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章