日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > > 架構師社區(qū)
[導讀]在JDK中,提供了這樣一種功能:它能夠將復雜的邏輯拆分成一個個簡單的邏輯來并行執(zhí)行,待每個并行執(zhí)行的邏輯執(zhí)行完成后,再將各個結果進行匯總,得出最終的結果數(shù)據(jù)。有點像Hadoop中的MapReduce。

寫在前面

在JDK中,提供了這樣一種功能:它能夠將復雜的邏輯拆分成一個個簡單的邏輯來并行執(zhí)行,待每個并行執(zhí)行的邏輯執(zhí)行完成后,再將各個結果進行匯總,得出最終的結果數(shù)據(jù)。有點像Hadoop中的MapReduce。

ForkJoin是由JDK1.7之后提供的多線程并發(fā)處理框架。ForkJoin框架的基本思想是分而治之。什么是分而治之?分而治之就是將一個復雜的計算,按照設定的閾值分解成多個計算,然后將各個計算結果進行匯總。相應的,F(xiàn)orkJoin將復雜的計算當做一個任務,而分解的多個計算則是當做一個個子任務來并行執(zhí)行。

注:文章已同步收錄到:https://github.com/sunshinelyz/technology-binghe 和 ?https://gitee.com/binghe001/technology-binghe 。如果文件對你有點幫助,別忘記給個Star哦!如果小伙伴們有任何疑問,都可以加我微信【sun_shine_lyz】進行交流哦!

Java并發(fā)編程的發(fā)展

對于Java語言來說,生來就支持多線程并發(fā)編程,在并發(fā)編程領域也是在不斷發(fā)展的。Java在其發(fā)展過程中對并發(fā)編程的支持越來越完善也正好印證了這一點。

  • Java 1 支持thread,synchronized。
  • Java 5 引入了 thread pools, blocking queues, concurrent collections,locks, condition queues。
  • Java 7 加入了fork-join庫。
  • Java 8 加入了 parallel streams。

并發(fā)與并行

并發(fā)和并行在本質上還是有所區(qū)別的。

并發(fā)

并發(fā)指的是在同一時刻,只有一個線程能夠獲取到CPU執(zhí)行任務,而多個線程被快速的輪換執(zhí)行,這就使得在宏觀上具有多個線程同時執(zhí)行的效果,并發(fā)不是真正的同時執(zhí)行,并發(fā)可以使用下圖表示。

并發(fā)編程中一種經典的分而治之的思想??!
并行

并行指的是無論何時,多個線程都是在多個CPU核心上同時執(zhí)行的,是真正的同時執(zhí)行。

并發(fā)編程中一種經典的分而治之的思想?。? >
  </figure>
  <h2 style=分治法

基本思想

把一個規(guī)模大的問題劃分為規(guī)模較小的子問題,然后分而治之,最后合并子問題的解得到原問題的解。

步驟

①分割原問題;

②求解子問題;

③合并子問題的解為原問題的解。

我們可以使用如下偽代碼來表示這個步驟。

if(任務很小){
????直接計算得到結果
}else{
????分拆成N個子任務
????調用子任務的fork()進行計算
????調用子任務的join()合并計算結果
}

在分治法中,子問題一般是相互獨立的,因此,經常通過遞歸調用算法來求解子問題。

典型應用

  • 二分搜索

  • 大整數(shù)乘法

  • Strassen矩陣乘法

  • 棋盤覆蓋

  • 合并排序

  • 快速排序

  • 線性時間選擇

  • 漢諾塔

ForkJoin并行處理框架

ForkJoin框架概述

Java 1.7 引入了一種新的并發(fā)框架—— Fork/Join Framework,主要用于實現(xiàn)“分而治之”的算法,特別是分治之后遞歸調用的函數(shù)。

ForkJoin框架的本質是一個用于并行執(zhí)行任務的框架, 能夠把一個大任務分割成若干個小任務,最終匯總每個小任務結果后得到大任務的計算結果。在Java中,F(xiàn)orkJoin框架與ThreadPool共存,并不是要替換ThreadPool

其實,在Java 8中引入的并行流計算,內部就是采用的ForkJoinPool來實現(xiàn)的。例如,下面使用并行流實現(xiàn)打印數(shù)組元組的程序。

public?class?SumArray?{
????public?static?void?main(String[]?args){
????????List?numberList?=?Arrays.asList(1,2,3,4,5,6,7,8,9);
????????numberList.parallelStream().forEach(System.out::println);
????}
}

這段代碼的背后就使用到了ForkJoinPool。

說到這里,可能有讀者會問:可以使用線程池的ThreadPoolExecutor來實現(xiàn)???為什么要使用ForkJoinPool?。縁orkJoinPool是個什么鬼?。浚?/strong>?接下來,我們就來回答這個問題。

ForkJoin框架原理

ForkJoin框架是從jdk1.7中引入的新特性,它同ThreadPoolExecutor一樣,也實現(xiàn)了Executor和ExecutorService接口。它使用了一個無限隊列來保存需要執(zhí)行的任務,而線程的數(shù)量則是通過構造函數(shù)傳入,如果沒有向構造函數(shù)中傳入指定的線程數(shù)量,那么當前計算機可用的CPU數(shù)量會被設置為線程數(shù)量作為默認值。

ForkJoinPool主要使用?分治法(Divide-and-Conquer Algorithm)?來解決問題。典型的應用比如快速排序算法。這里的要點在于,F(xiàn)orkJoinPool能夠使用相對較少的線程來處理大量的任務。比如要對1000萬個數(shù)據(jù)進行排序,那么會將這個任務分割成兩個500萬的排序任務和一個針對這兩組500萬數(shù)據(jù)的合并任務。以此類推,對于500萬的數(shù)據(jù)也會做出同樣的分割處理,到最后會設置一個閾值來規(guī)定當數(shù)據(jù)規(guī)模到多少時,停止這樣的分割處理。比如,當元素的數(shù)量小于10時,會停止分割,轉而使用插入排序對它們進行排序。那么到最后,所有的任務加起來會有大概200萬+個。問題的關鍵在于,對于一個任務而言,只有當它所有的子任務完成之后,它才能夠被執(zhí)行。

所以當使用ThreadPoolExecutor時,使用分治法會存在問題,因為ThreadPoolExecutor中的線程無法向任務隊列中再添加一個任務并在等待該任務完成之后再繼續(xù)執(zhí)行。而使用ForkJoinPool就能夠解決這個問題,它就能夠讓其中的線程創(chuàng)建新的任務,并掛起當前的任務,此時線程就能夠從隊列中選擇子任務執(zhí)行。

那么使用ThreadPoolExecutor或者ForkJoinPool,性能上會有什么差異呢?

首先,使用ForkJoinPool能夠使用數(shù)量有限的線程來完成非常多的具有父子關系的任務,比如使用4個線程來完成超過200萬個任務。但是,使用ThreadPoolExecutor時,是不可能完成的,因為ThreadPoolExecutor中的Thread無法選擇優(yōu)先執(zhí)行子任務,需要完成200萬個具有父子關系的任務時,也需要200萬個線程,很顯然這是不可行的,也是很不合理的?。?/p>

工作竊取算法

假如我們需要做一個比較大的任務,我們可以把這個任務分割為若干互不依賴的子任務,為了減少線程間的競爭,于是把這些子任務分別放到不同的隊列里,并為每個隊列創(chuàng)建一個單獨的線程來執(zhí)行隊列里的任務,線程和隊列一一對應,比如A線程負責處理A隊列里的任務。但是有的線程會先把自己隊列里的任務干完,而其他線程對應的隊列里還有任務等待處理。干完活的線程與其等著,不如去幫其他線程干活,于是它就去其他線程的隊列里竊取一個任務來執(zhí)行。而在這時它們會訪問同一個隊列,所以為了減少竊取任務線程和被竊取任務線程之間的競爭,通常會使用雙端隊列,被竊取任務線程永遠從雙端隊列的頭部拿任務執(zhí)行,而竊取任務的線程永遠從雙端隊列的尾部拿任務執(zhí)行。

工作竊取算法的優(yōu)點:充分利用線程進行并行計算,并減少了線程間的競爭。

工作竊取算法的缺點:在某些情況下還是存在競爭,比如雙端隊列里只有一個任務時。并且該算法會消耗更多的系統(tǒng)資源,比如創(chuàng)建多個線程和多個雙端隊列。

Fork/Join框架局限性:

對于Fork/Join框架而言,當一個任務正在等待它使用Join操作創(chuàng)建的子任務結束時,執(zhí)行這個任務的工作線程查找其他未被執(zhí)行的任務,并開始執(zhí)行這些未被執(zhí)行的任務,通過這種方式,線程充分利用它們的運行時間來提高應用程序的性能。為了實現(xiàn)這個目標,F(xiàn)ork/Join框架執(zhí)行的任務有一些局限性。

(1)任務只能使用Fork和Join操作來進行同步機制,如果使用了其他同步機制,則在同步操作時,工作線程就不能執(zhí)行其他任務了。比如,在Fork/Join框架中,使任務進行了睡眠,那么,在睡眠期間內,正在執(zhí)行這個任務的工作線程將不會執(zhí)行其他任務了。(2)在Fork/Join框架中,所拆分的任務不應該去執(zhí)行IO操作,比如:讀寫數(shù)據(jù)文件。(3)任務不能拋出檢查異常,必須通過必要的代碼來出來這些異常。

ForkJoin框架的實現(xiàn)

ForkJoin框架中一些重要的類如下所示。

并發(fā)編程中一種經典的分而治之的思想??!

ForkJoinPool 框架中涉及的主要類如下所示。

1.ForkJoinPool類

實現(xiàn)了ForkJoin框架中的線程池,由類圖可以看出,F(xiàn)orkJoinPool類實現(xiàn)了線程池的Executor接口。

我們也可以從下圖中看出ForkJoinPool的類圖關系。

并發(fā)編程中一種經典的分而治之的思想!!

其中,可以使用Executors.newWorkStealPool()方法創(chuàng)建ForkJoinPool。

ForkJoinPool中提供了如下提交任務的方法。

public?void?execute(ForkJoinTask?task)
public?void?execute(Runnable?task)
public??T?invoke(ForkJoinTask?task)
public??List>?invokeAll(Collection>?tasks)?
public??ForkJoinTask?submit(ForkJoinTask?task)
public??ForkJoinTask?submit(Callable?task)
public??ForkJoinTask?submit(Runnable?task,?T?result)
public?ForkJoinTask?submit(Runnable?task)

2.ForkJoinWorkerThread類

實現(xiàn)ForkJoin框架中的線程。

3.ForkJoinTask

ForkJoinTask封裝了數(shù)據(jù)及其相應的計算,并且支持細粒度的數(shù)據(jù)并行。ForkJoinTask比線程要輕量,F(xiàn)orkJoinPool中少量工作線程能夠運行大量的ForkJoinTask。

ForkJoinTask類中主要包括兩個方法fork()和join(),分別實現(xiàn)任務的分拆與合并。

fork()方法類似于Thread.start(),但是它并不立即執(zhí)行任務,而是將任務放入工作隊列中。跟Thread.join()方法不同,F(xiàn)orkJoinTask的join()方法并不簡單的阻塞線程,而是利用工作線程運行其他任務,當一個工作線程中調用join(),它將處理其他任務,直到注意到目標子任務已經完成。

我們可以使用下圖來表示這個過程。

并發(fā)編程中一種經典的分而治之的思想??!

ForkJoinTask有3個子類:

并發(fā)編程中一種經典的分而治之的思想!!
  • RecursiveAction:無返回值的任務。

  • RecursiveTask:有返回值的任務。

  • CountedCompleter:完成任務后將觸發(fā)其他任務。

4.RecursiveTask

有返回結果的ForkJoinTask實現(xiàn)Callable。

5.RecursiveAction類

無返回結果的ForkJoinTask實現(xiàn)Runnable。

6.CountedCompleter

在任務完成執(zhí)行后會觸發(fā)執(zhí)行一個自定義的鉤子函數(shù)。

ForkJoin示例程序

package?io.binghe.concurrency.example.aqs;
?
import?lombok.extern.slf4j.Slf4j;
import?java.util.concurrent.ForkJoinPool;
import?java.util.concurrent.Future;
import?java.util.concurrent.RecursiveTask;
@Slf4j
public?class?ForkJoinTaskExample?extends?RecursiveTask<Integer>?{
????public?static?final?int?threshold?=?2;
????private?int?start;
????private?int?end;
????public?ForkJoinTaskExample(int?start,?int?end)?{
????????this.start?=?start;
????????this.end?=?end;
????}
????@Override
????protected?Integer?compute()?{
????????int?sum?=?0;
????????//如果任務足夠小就計算任務
????????boolean?canCompute?=?(end?-?start)?<=?threshold;
????????if?(canCompute)?{
????????????for?(int?i?=?start;?i?<=?end;?i++)?{
????????????????sum?+=?i;
????????????}
????????}?else?{
????????????//?如果任務大于閾值,就分裂成兩個子任務計算
????????????int?middle?=?(start?+?end)?/?2;
????????????ForkJoinTaskExample?leftTask?=?new?ForkJoinTaskExample(start,?middle);
????????????ForkJoinTaskExample?rightTask?=?new?ForkJoinTaskExample(middle?+?1,?end);
?
????????????//?執(zhí)行子任務
????????????leftTask.fork();
????????????rightTask.fork();
?
????????????//?等待任務執(zhí)行結束合并其結果
????????????int?leftResult?=?leftTask.join();
????????????int?rightResult?=?rightTask.join();
?
????????????//?合并子任務
????????????sum?=?leftResult?+?rightResult;
????????}
????????return?sum;
????}
????public?static?void?main(String[]?args)?{
????????ForkJoinPool?forkjoinPool?=?new?ForkJoinPool();
?
????????//生成一個計算任務,計算1+2+3+4
????????ForkJoinTaskExample?task?=?new?ForkJoinTaskExample(1,?100);
?
????????//執(zhí)行一個任務
????????Future?result?=?forkjoinPool.submit(task);
?
????????try?{
????????????log.info("result:{}",?result.get());
????????}?catch?(Exception?e)?{
????????????log.error("exception",?e);
????????}
????}
}

特別推薦一個分享架構+算法的優(yōu)質內容,還沒關注的小伙伴,可以長按關注一下:

并發(fā)編程中一種經典的分而治之的思想!!

并發(fā)編程中一種經典的分而治之的思想?。? ></p></pre>
  <p style=并發(fā)編程中一種經典的分而治之的思想??!

長按訂閱更多精彩▼

并發(fā)編程中一種經典的分而治之的思想!!

如有收獲,點個在看,誠摯感謝

免責聲明:本文內容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: 驅動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設備,其驅動電源的性能直接關系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅動電源設計中至關重要的兩個環(huán)節(jié),集成化方案的設計成為提升電機驅動性能的關鍵。

關鍵字: 工業(yè)電機 驅動電源

LED 驅動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設備的使用壽命。然而,在實際應用中,LED 驅動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設計、生...

關鍵字: 驅動電源 照明系統(tǒng) 散熱

根據(jù)LED驅動電源的公式,電感內電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關鍵字: LED 設計 驅動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產業(yè)的重要發(fā)展方向。電動汽車的核心技術之一是電機驅動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅動系統(tǒng)中的關鍵元件,其性能直接影響到電動汽車的動力性能和...

關鍵字: 電動汽車 新能源 驅動電源

在現(xiàn)代城市建設中,街道及停車場照明作為基礎設施的重要組成部分,其質量和效率直接關系到城市的公共安全、居民生活質量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關鍵字: 發(fā)光二極管 驅動電源 LED

LED通用照明設計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關鍵字: LED 驅動電源 功率因數(shù)校正

在LED照明技術日益普及的今天,LED驅動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關鍵字: LED照明技術 電磁干擾 驅動電源

開關電源具有效率高的特性,而且開關電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅動電源

關鍵字: LED 驅動電源 開關電源

LED驅動電源是把電源供應轉換為特定的電壓電流以驅動LED發(fā)光的電壓轉換器,通常情況下:LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: LED 隧道燈 驅動電源
關閉