Java Fork/Join框架。本站提示廣大學習愛好者:(Java Fork/Join框架)文章只能為提供參考,不一定能成為您想要的結果。以下是Java Fork/Join框架正文
Fork/Join框架是ExecutorService接口的一個完成,經由過程它我們可以完成多過程。Fork/Join可以用來將一個年夜義務遞歸的拆分為多個小義務,目的是充足應用一切的資本盡量加強運用的機能。
和任何ExecutorService接口的完成一樣,Fork/Join也會應用線程池來散布式的治理任務線程。Fork/Join框架的奇特的地方在於它應用了work-stealing(任務盜取)算法。經由過程這個算法,任務線程在無事可做時可以盜取其它正在忙碌的線程的義務來履行。
Fork/Join框架的焦點是ForkJoinPool類,一個AbstractExecutorService類的子類。ForkJoinPool完成了焦點的work-stealing算法並可以履行ForkJoinTask處置。
基本用法
應用Fork/Join框架的第一步是編寫履行碎片義務的代碼。要編寫的代碼相似以下偽代碼:
if 義務足夠小: 直接履行義務 else: 將義務切成兩個小義務 履行兩個小義務並期待成果
應用ForkJoinTask子類來封裝如上的代碼,平日會應用一些JDK供給的類,應用的有RecursiveTask(這個類會前往一個成果)和RecursiveAction兩個類。
在預備好ForkJoinTask子類後,創立一個代表一切義務的對象,並將之傳遞給一個ForkJoinPool實例的invoke()辦法。
由隱約到清楚
為了幫助懂得Fork/Join框架是若何任務的,我們應用一個案例來停止解釋:好比對一張圖片停止隱約處置。我們用一個整型數組表現圖片,個中的每一個數值代表一個像素的色彩。被隱約的圖片也用一個一致長度的數組來表現。
履行隱約是經由過程對代表圖片的每一個像素停止處置完成的。盤算每一個像素與其四周像素的均值(紅黃藍三原色的均值),盤算生成的成果數組就是隱約後的圖片。因為代表圖象的平日都是一個年夜數組,全部處置進程須要平日會須要許多時光。可使用Fork/Join框架應用多處置器體系上的並發處置優勢來停止提速。上面是一個能夠的完成:
package com.zhyea.robin; import java.util.concurrent.RecursiveAction; public class ForkBlur extends RecursiveAction { private int[] mSource; private int mStart; private int mLength; private int[] mDestination; // 處置窗口年夜小; 須要是一個奇數. private int mBlurWidth = 15; public ForkBlur(int[] src, int start, int length, int[] dst) { mSource = src; mStart = start; mLength = length; mDestination = dst; } protected void computeDirectly() { int sidePixels = (mBlurWidth - 1) / 2; for (int index = mStart; index < mStart + mLength; index++) { // 盤算均勻值. float rt = 0, gt = 0, bt = 0; for (int mi = -sidePixels; mi <= sidePixels; mi++) { int mindex = Math.min(Math.max(mi + index, 0), mSource.length - 1); int pixel = mSource[mindex]; rt += (float) ((pixel & 0x00ff0000) >> 16) / mBlurWidth; gt += (float) ((pixel & 0x0000ff00) >> 8) / mBlurWidth; bt += (float) ((pixel & 0x000000ff) >> 0) / mBlurWidth; } // 重組目的像素. int dpixel = (0xff000000) | (((int) rt) << 16) | (((int) gt) << 8) | (((int) bt) << 0); mDestination[index] = dpixel; } } .... }
如今完成籠統辦法compute(),在這個辦法中既完成了隱約操作,也完成了將一個義務拆分紅兩個小義務。這裡僅是簡略根據數組長度來決議是直接履行義務照樣將之拆分紅兩個小義務:
protected static int sThreshold = 100000; protected void compute() { if (mLength < sThreshold) { computeDirectly(); return; } int split = mLength / 2; invokeAll(new ForkBlur(mSource, mStart, split, mDestination), new ForkBlur(mSource, mStart + split, mLength - split, mDestination)); }
由於下面這些辦法的完成是界說在RecursiveAction的一個子類中,可以直接在一個ForkJoinPool中創立並運轉義務。詳細步調以下:
1. 創立一個代表要履行的義務的對象:
// src 表現源圖片像素的數組 // dst 表現生成的圖片的像素 ForkBlur fb = new ForkBlur(src, 0, src.length, dst);
2. 創立一個運轉義務的ForkJoinPool實例:
ForkJoinPool pool = new ForkJoinPool();
3. 運轉義務:
pool.invoke(fb);
在源代碼中還包括了一些創立目的圖片的代碼。詳細參考ForkBlur示例。
尺度完成
要應用Fork/Join框架按自界說的算法在多核體系上履行並發義務固然須要完成自界說的類了(好比之前我們完成的ForkBlur類)。除此以外,在JavaSE中曾經在普遍應用Fork/Join框架的一些特征了。好比Java8中的java.util.Arrays類的parallelSort()辦法就應用了Fork/Join框架。詳細可以參考Java API文檔。
Fork/Join框架的另外一個完成在java.util.streams包下,這也是java8的Lambda特征的一部門。