ForkJoinPool

1近上、什么是ForkJoinPool

雖然目前處理器核心數(shù)已經(jīng)發(fā)展到很大數(shù)目,但是按任務(wù)并發(fā)處理并不能完全充分的利用處理器資源,因?yàn)橐话愕膽?yīng)用程序沒(méi)有那么多的并發(fā)處理任務(wù)谁鳍。基于這種現(xiàn)狀,考慮把一個(gè)任務(wù)拆分成多個(gè)單元倘潜,每個(gè)單元分別得到執(zhí)行绷柒,最后合并每個(gè)單元的結(jié)果。 有些線(xiàn)程一直處于忙碌狀態(tài)涮因,而有些線(xiàn)程卻一直空閑狀態(tài)废睦,這么可以充分的利用處理器資源

Fork/Join框架是JAVA7提供的一個(gè)用于并行執(zhí)行任務(wù)的框架,是一個(gè)把大任務(wù)分割成若干小任務(wù)养泡,最終匯總每個(gè)小任務(wù)結(jié)果得到大任務(wù)結(jié)果的框架嗜湃。

ForkJoinPool主要采用分治算法 和 工作竊取算法

2、分治法

分治法的基本思想是將一個(gè)規(guī)模為N的問(wèn)題分解為K個(gè)規(guī)模較小的子問(wèn)題澜掩,這些子問(wèn)題的相互獨(dú)立且與原問(wèn)題的性質(zhì)相同购披,求出子問(wèn)題的解之后,將這些解合并肩榕,就可以得到原有問(wèn)題的解刚陡。是一種分目標(biāo)完成的程序算法。


image.png

3株汉、工作竊取算法

一個(gè)大任務(wù)拆分成多個(gè)小任務(wù)筐乳,為了減少線(xiàn)程間的競(jìng)爭(zhēng),把這些子任務(wù)分別放到不同的隊(duì)列中乔妈,并且每個(gè)隊(duì)列都有單獨(dú)的線(xiàn)程來(lái)執(zhí)行隊(duì)列里的任務(wù)蝙云,線(xiàn)程和隊(duì)列一一對(duì)應(yīng)。

但是會(huì)出現(xiàn)這樣一種情況:A線(xiàn)程處理完了自己隊(duì)列的任務(wù)路召,B線(xiàn)程的隊(duì)列里還有很多任務(wù)要處理勃刨。

A是一個(gè)很熱情的線(xiàn)程,想過(guò)去幫忙股淡,但是如果兩個(gè)線(xiàn)程訪(fǎng)問(wèn)同一個(gè)隊(duì)列身隐,會(huì)產(chǎn)生競(jìng)爭(zhēng),所以A想了一個(gè)辦法揣非,從雙端隊(duì)列的尾部拿任務(wù)執(zhí)行抡医。而B(niǎo)線(xiàn)程永遠(yuǎn)是從雙端隊(duì)列的頭部拿任務(wù)執(zhí)行。

image.png

注意:線(xiàn)程池中的每個(gè)線(xiàn)程都有自己的工作隊(duì)列(PS早敬,這一點(diǎn)和ThreadPoolExecutor不同忌傻,ThreadPoolExecutor是所有線(xiàn)程公用一個(gè)工作隊(duì)列搞监,所有線(xiàn)程都從這個(gè)工作隊(duì)列中取任務(wù))琐驴,當(dāng)自己隊(duì)列中的任務(wù)都完成以后秤标,會(huì)從其它線(xiàn)程的工作隊(duì)列中偷一個(gè)任務(wù)執(zhí)行苍姜,這樣可以充分利用資源衙猪。(特別注意)

工作竊取算法的優(yōu)點(diǎn):

利用了線(xiàn)程進(jìn)行并行計(jì)算布近,減少了線(xiàn)程間的競(jìng)爭(zhēng)撑瞧。

工作竊取算法的缺點(diǎn):

1预伺、如果雙端隊(duì)列中只有一個(gè)任務(wù)時(shí),線(xiàn)程間會(huì)存在競(jìng)爭(zhēng)算谈。(只有一個(gè)任務(wù)的時(shí)候需要特殊處理)

2料滥、竊取算法消耗了更多的系統(tǒng)資源葵腹,如會(huì)創(chuàng)建多個(gè)線(xiàn)程和多個(gè)雙端隊(duì)列屿岂。

4、主要類(lèi)

1爷怀、ForkJoinTask:

使用該框架运授,需要?jiǎng)?chuàng)建一個(gè)ForkJoin任務(wù),它提供在任務(wù)中執(zhí)行fork和join操作的機(jī)制吁朦。一般情況下逗宜,我們并不需要直接繼承ForkJoinTask類(lèi),只需要繼承它的子類(lèi)囤屹,它的子類(lèi)有兩個(gè):
RecursiveAction:用于沒(méi)有返回結(jié)果的任務(wù)牺丙。
RecursiveTask:用于有返回結(jié)果的任務(wù)冲簿。

2亿昏、ForkJoinPool:

任務(wù)ForkJoinTask需要通過(guò)ForkJoinPool來(lái)執(zhí)行角钩。

5、例子

計(jì)算1到40的累加和惨险,當(dāng)間隔大于limit脊髓,則繼續(xù)遞歸

package com.concurrency2;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class MyTest13 {
    public static void main(String[] args) {
        ForkJoinPool forkJoinPool = new ForkJoinPool(2);
        MyTask myTask = new MyTask(1, 40);

        int result = forkJoinPool.invoke(myTask);

        System.out.println(result);

        forkJoinPool.shutdown();
    }
}

class MyTask extends RecursiveTask<Integer> {
    private int limit = 4;

    private int firstIndex;

    private int lastIndex;

    public MyTask(int firstIndex, int lastIndex) {
        this.firstIndex = firstIndex;
        this.lastIndex = lastIndex;
    }

    @Override
    protected Integer compute() {
        int result = 0;

        int gap = lastIndex - firstIndex;

        boolean flag = gap <= limit;

        if (flag) {
            System.out.println(Thread.currentThread().getName());

            for(int i = firstIndex;i <= lastIndex;i ++)
            {
                result += i;
            }
        } else {
            int middleIndex = (firstIndex + lastIndex) / 2;

            MyTask leftTask = new MyTask(firstIndex, middleIndex);
            MyTask rightTask = new MyTask(middleIndex + 1, lastIndex);

            invokeAll(leftTask, rightTask);

            int leftTaskResult = leftTask.join();
            int rightTaskResult = rightTask.join();

            result = leftTaskResult + rightTaskResult;
        }

        return result;
    }
}

輸出

ForkJoinPool-1-worker-1
ForkJoinPool-1-worker-0
ForkJoinPool-1-worker-1
ForkJoinPool-1-worker-0
ForkJoinPool-1-worker-1
ForkJoinPool-1-worker-0
ForkJoinPool-1-worker-1
ForkJoinPool-1-worker-0
820
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市将硝,隨后出現(xiàn)的幾起案子恭朗,更是在濱河造成了極大的恐慌依疼,老刑警劉巖痰腮,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件律罢,死亡現(xiàn)場(chǎng)離奇詭異膀值,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)误辑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)稀余,“玉大人睛琳,你說(shuō)我怎么就攤上這事盒蟆。” “怎么了寒屯?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我菩掏,道長(zhǎng)魂角,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任智绸,我火速辦了婚禮野揪,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瞧栗。我一直安慰自己斯稳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布迹恐。 她就那樣靜靜地躺著挣惰,像睡著了一般。 火紅的嫁衣襯著肌膚如雪系草。 梳的紋絲不亂的頭發(fā)上通熄,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天唆涝,我揣著相機(jī)與錄音找都,去河邊找鬼。 笑死廊酣,一個(gè)胖子當(dāng)著我的面吹牛能耻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播亡驰,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼晓猛,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了凡辱?” 一聲冷哼從身側(cè)響起戒职,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎透乾,沒(méi)想到半個(gè)月后洪燥,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體磕秤,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年捧韵,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了市咆。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡再来,死狀恐怖蒙兰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情芒篷,我是刑警寧澤搜变,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站针炉,受9級(jí)特大地震影響痹雅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜糊识,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一绩社、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧赂苗,春花似錦愉耙、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至败砂,卻和暖如春赌渣,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留础倍,地道東北人拌禾。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容