java中fork函數_java中的forkjoin框架的使用

42bd13c6670274f0993c5c92419dc87e.png

fork join框架是java 7中引入框架,這個框架的引入主要是為了提升并行計算的能力。

fork join主要有兩個步驟,第一就是fork,將一個大任務分成很多個小任務,第二就是join,將第一個任務的結果join起來,生成最后的結果。如果第一步中并沒有任何返回值,join將會等到所有的小任務都結束。

還記得之前的文章我們講到了thread pool的基本結構嗎?

ExecutorService - ForkJoinPool 用來調用任務執行。

workerThread - ForkJoinWorkerThread 工作線程,用來執行具體的任務。

task - ForkJoinTask 用來定義要執行的任務。

下面我們從這三個方面來詳細講解fork join框架。

ForkJoinPool

ForkJoinPool是一個ExecutorService的一個實現,它提供了對工作線程和線程池的一些便利管理方法。

public class ForkJoinPool extends AbstractExecutorService

一個work thread一次只能處理一個任務,但是ForkJoinPool并不會為每個任務都創建一個單獨的線程,它會使用一個特殊的數據結構double-ended queue來存儲任務。這樣的結構可以方便的進行工作竊取(work-stealing)。

什么是work-stealing呢?

默認情況下,work thread從分配給自己的那個隊列頭中取出任務。如果這個隊列是空的,那么這個work thread會從其他的任務隊列尾部取出任務來執行,或者從全局隊列中取出。這樣的設計可以充分利用work thread的性能,提升并發能力。

下面看下怎么創建一個ForkJoinPool。

最常見的方法就是使用ForkJoinPool.commonPool()來創建,commonPool()為所有的ForkJoinTask提供了一個公共默認的線程池。

ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();

另外一種方式是使用構造函數:

ForkJoinPool forkJoinPool = new ForkJoinPool(2);

這里的參數是并行級別,2指的是線程池將會使用2個處理器核心。

ForkJoinWorkerThread

ForkJoinWorkerThread是使用在ForkJoinPool的工作線程。

public class ForkJoinWorkerThread extends Thread

}

和一般的線程不一樣的是它定義了兩個變量:

final ForkJoinPool pool; // the pool this thread works in

final ForkJoinPool.WorkQueue workQueue; // work-stealing mechanics

一個是該worker thread所屬的ForkJoinPool。 另外一個是支持 work-stealing機制的Queue。

再看一下它的run方法:

public void run() {

if (workQueue.array == null) { // only run once

Throwable exception = null;

try {

onStart();

pool.runWorker(workQueue);

} catch (Throwable ex) {

exception = ex;

} finally {

try {

onTermination(exception);

} catch (Throwable ex) {

if (exception == null)

exception = ex;

} finally {

pool.deregisterWorker(this, exception);

}

}

}

}

簡單點講就是從Queue中取出任務執行。

ForkJoinTask

ForkJoinTask是ForkJoinPool中運行的任務類型。通常我們會用到它的兩個子類:RecursiveAction和RecursiveTask。

他們都定義了一個需要實現的compute()方法用來實現具體的業務邏輯。不同的是RecursiveAction只是用來執行任務,而RecursiveTask可以有返回值。

既然兩個類都帶了Recursive,那么具體的實現邏輯也會跟遞歸有關,我們舉個使用RecursiveAction來打印字符串的例子:

public class CustomRecursiveAction extends RecursiveAction {

private String workload = "";

private static final int THRESHOLD = 4;

private static Logger logger =

Logger.getAnonymousLogger();

public CustomRecursiveAction(String workload) {

this.workload = workload;

}

@Override

protected void compute() {

if (workload.length() > THRESHOLD) {

ForkJoinTask.invokeAll(createSubtasks());

} else {

processing(workload);

}

}

private List createSubtasks() {

List subtasks = new ArrayList<>();

String partOne = workload.substring(0, workload.length() / 2);

String partTwo = workload.substring(workload.length() / 2, workload.length());

subtasks.add(new CustomRecursiveAction(partOne));

subtasks.add(new CustomRecursiveAction(partTwo));

return subtasks;

}

private void processing(String work) {

String result = work.toUpperCase();

logger.info("This result - (" + result + ") - was processed by "

+ Thread.currentThread().getName());

}

}

上面的例子使用了二分法來打印字符串。

我們再看一個RecursiveTask的例子:

public class CustomRecursiveTask extends RecursiveTask {

private int[] arr;

private static final int THRESHOLD = 20;

public CustomRecursiveTask(int[] arr) {

this.arr = arr;

}

@Override

protected Integer compute() {

if (arr.length > THRESHOLD) {

return ForkJoinTask.invokeAll(createSubtasks())

.stream()

.mapToInt(ForkJoinTask::join)

.sum();

} else {

return processing(arr);

}

}

private Collection createSubtasks() {

List dividedTasks = new ArrayList<>();

dividedTasks.add(new CustomRecursiveTask(

Arrays.copyOfRange(arr, 0, arr.length / 2)));

dividedTasks.add(new CustomRecursiveTask(

Arrays.copyOfRange(arr, arr.length / 2, arr.length)));

return dividedTasks;

}

private Integer processing(int[] arr) {

return Arrays.stream(arr)

.filter(a -> a > 10 && a < 27)

.map(a -> a * 10)

.sum();

}

}

和上面的例子很像,不過這里我們需要有返回值。

在ForkJoinPool中提交Task

有了上面的兩個任務,我們就可以在ForkJoinPool中提交了:

int[] intArray= {12,12,13,14,15};

CustomRecursiveTask customRecursiveTask= new CustomRecursiveTask(intArray);

int result = forkJoinPool.invoke(customRecursiveTask);

System.out.println(result);

上面的例子中,我們使用invoke來提交,invoke將會等待任務的執行結果。

如果不使用invoke,我們也可以將其替換成fork()和join():

customRecursiveTask.fork();

int result2= customRecursiveTask.join();

System.out.println(result2);

fork() 是將任務提交給pool,但是并不觸發執行, join()將會真正的執行并且得到返回結果。

本文的例子可以參考https://github.com/ddean2009/learn-java-concurrency/tree/master/forkjoin

到此這篇關于java中的fork join框架的使用的文章就介紹到這了,更多相關java fork join框架內容請搜索云海天教程以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持云海天教程!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/530295.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/530295.shtml
英文地址,請注明出處:http://en.pswp.cn/news/530295.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java h264起始碼_h.264 – 使用H264視頻的起始碼

有兩種H.264流格式,有時也稱為>附件B(在原始H.264流中找到)> AVCC(在像MP4這樣的容器中找到)H.264流由NAL(包裝單位)組成(1)附件B&#xff1a;在每個NAL單元的字節[x00] [x00] [x00] [x01]之前有4字節的起始碼.[start code]--[NAL]--[start code]--[NAL] etc(2)AVCC&…

java中已定義類型car_Java 8 習慣用語(8):Java 知道您的類型

Java?8是第一個支持類型推斷的 Java 版本&#xff0c;而且它僅對 lambda 表達式支持此功能。在 lambda表達式中使用類型推斷具有強大的作用&#xff0c;它將幫助您做好準備以應對未來的 Java版本&#xff0c;在今后的版本中還會將類型推斷用于變量等更多可能。這里的訣竅在于恰…

ATM柜員機JAVA課程設計_ATM柜員機學年論文設計(Java課程設計)

內容簡介&#xff1a;ATM柜員機學年論文設計(Java課程設計)&#xff0c;共23頁&#xff0c;4599字&#xff0c;附源程序。一&#xff0e; 程序介紹3二&#xff0e; 開發環境搭建31. MyEclipse 5.5.1 GA安裝32. MyEclipse Designer 圖形設計插件安裝33. MySQL數據庫安裝4三&…

mysql 結果集什么意思_結果集中的mysql“和”邏輯

假設我有一個類似以下的數據集&#xff1a;table fooid | employeeType | employeeID-------------------------1 | Developer | 12 | Developer | 23 | Developer | 34 | Manager | 15 | Manager | 46 | Manager | 57 | CEO | 18 | CEO | 6我想運行一個查詢,該查詢將返回所有e…

opencv java 去干擾_java - OpenCV Java修補圖像格式要求 - 堆棧內存溢出

一直試圖讓修復工作在Android上進行&#xff0c;int height (int) viewMat.size().height;int width (int) viewMat.size().width;Mat maskMat new Mat();maskMat.create(viewMat.size(), CvType.CV_8U);maskMat.setTo(bColor);Point r1 new Point(width/2-width/10, heigh…

java中 set集合_第8篇 Java中的集合(Set)

Java 集合的 Set 接口Set類型與List類型的區別Set&#xff1a; 無序、不可重復List&#xff1a; 有序、可重復1、HashSetHashSet的存儲結構&#xff1a;HashMap特點&#xff1a;HashSet通過比較存放的哈希碼(hashCode)來確定對象存放的位置當兩個對象的哈希值相等時&#xff0c…

android mysql實現登錄注冊_android簡單登陸和注冊功能實現+SQLite數據庫學習

android簡單登陸和注冊功能實現SQLite數據庫學習發布時間&#xff1a;2018-07-04 17:23,瀏覽次數&#xff1a;1027, 標簽&#xff1a;androidSQLite這里我只是建立了一個用簡單的存儲用戶名和密碼的表單MyDBHelper.java<>public class MyDBHelper extends SQLiteOpenHelp…

java web 來源頁_Java:Java Web--分頁效果

先來看一看分頁的實現原理萬能公式.jpg項目目錄.PNG首先,新建Java Web項目一. 梳理業務邏輯重定向到URL(跳轉到StudentViewAction頁面)//index.jsp頁面1.從頁面接收可變的值2.接收值有問題時,初始化為13.如果沒有問題,把String類型接收值強轉成Integer4.實例DAO方法,調用findSt…

java 瀏覽器 安全_安全策略-IE瀏覽器防黑十大秘籍

1.管理好Cookie在IE6.0中&#xff0c;打開“工具”→“Internet選項”→“隱私”對話框&#xff0c;這里設定了“阻止所有Cookie”、“高”、“中高”、“中”、“低”、“接受所有Cookie”六個級別&#xff0c;你只要拖動滑塊就可以方便地進行設定&#xff0c;而點擊下方的“編…

什么是java中的枚舉法_enum枚舉javajava,enum枚舉使用詳解+,總結

enum 的全稱為 enumeration&#xff0c; 是 JDK 1.5 中引入的新特性&#xff0c;存放在 java.lang 包中。下面是我在使用 enum 過程中的一些經驗和總結。原始的接口定義常量語法(定義)創建枚舉類型要使用 enum 關鍵字&#xff0c;隱含了所創建的類型都是 java.lang.Enum 類的子…

java 審計 漏洞函數_Java Web代碼審計流程與漏洞函數

常見框架與組合常見框架Struts2SpringMVCSpring Boot框架執行流程View層&#xff1a;視圖層Controller層&#xff1a;表現層Service層&#xff1a;業務層Dom層&#xff1a;持久層常見組合SpringStruts2HibernateSpringSpringMVCMybatisSpring BootMybatis代碼審計方法根據業務功…

java前期_【JAVA】前期環境配置

一、java的環境配置及在eclipse中如何安裝JRE或JDK環境eclipse下載地址&#xff1a;JDK下載地址&#xff1a;1)安裝JDK或JRE注&#xff1a;JDK使用與開發者運用&#xff0c;其中包含了開發環境和運行環境。而JRE只包含了java的運行環境。2)配置設置執行路徑UNiX&#xff1a;在C…

php截取指定字符串之后,php截取字符串(截取指定字符串之間的字符串)

一、PHP截取兩個指定字符后邊的字符$a "123abc#456";$b (strpos($a,""));$c (strpos($a,"#"));echo substr($a,$b1,$c-1);二、常用截取字符串技巧。//構造字符串$str "ABCDEFGHIJKLMNOPQRSTUVWXYZ";echo "原字符串&#xff1a;…

php 日志按天截取,Laravel 日志管理:按日期切割日志

日志存儲Laravel 默認的錯誤文件記錄在一個文件里&#xff0c;隨著時間的推移&#xff0c;此文件將會變得巨大&#xff0c;不方便查閱。我們可以通過修改 config/app.php 配置文件中的 log 選項來配置 Laravel 使用的存儲機制。如果你希望每天產生日志都存放在不同的文件中&…

php xcache 方法,php xcache 解密

NO.2 /index.php?actionmd5webcrack 很強大,需要登陸論壇才能解密,點擊右上角的“register”進行注冊,都是一些簡單的單詞,應該能看懂吧?...() A.PHP B.JSP D.Ajax 4.配置 ...假設$aarray(‘x’,’y’);,則$aarray_pad...xcache 15 四個模塊 Admin Common Member Article 用戶…

ecshop category.php?id=4,categoryall.php

//by 瑯琊源碼 QQ:27392236define(IN_ECS, true);require dirname(__FILE__) . /includes/init.php;if ((DEBUG_MODE & 2) ! 2) {$smarty->caching true;}require ROOT_PATH . /includes/lib_area.php;$area_info get_area_info($province_id);$area_id $area_info[r…

php 獲取key的位置,PHP獲取當前所在目錄位置的方法

本文實例講述了PHP獲取當前所在目錄位置的方法。分享給大家供大家參考。具體分析如下&#xff1a;如果要獲取腳本文件的目錄&#xff0c;要應用函數getcwd()來實現。函數聲明如下&#xff1a;string getcwd ( void ) ;成功執行后返回當前目錄字符串&#xff0c;失敗返回FALSE。…

java8收集器,Java 8中的收集器collectionAndThen()方法

collectingAndThen()Java Collectors類中的方法使Collector適應于執行其他完成轉換。它返回執行下游收集器動作的收集器&#xff0c;然后執行附加的結束步驟。語法如下。static Collector collectingAndThen(Collector downstream, Functionfinisher)在這里&#xff0c;參數T-…

php 精度運算,PHP BC 庫(任意精度數字運算) | 網游世界

留意&#xff1a;備選參數$scale以設置運算精度(保留小數位)。bcscale(設置運算精度)bool bcscale ( int $scale )說明&#xff1a;設置運算精度(保留小數位)&#xff0c;成功返回TRUE否則為FALSE。bcadd(加法運算)string bcadd ( string $left_operand , string $right_operan…

php 不允許外部訪問,[日常] 解決mysql不允許外部訪問

1.在端口已經開放的情況下,ubuntu mysql 3306允許遠程訪問vim /etc/mysql/mysql.conf.d/mysqld.cnf注釋#bind-address 127.0.0.12.給用戶授權允許遠程訪問:grant all privileges on *.* to root"%" identified by "pwd" with grant option;flush privileg…