Fork_Join - Java多线程编程
生活随笔
收集整理的這篇文章主要介紹了
Fork_Join - Java多线程编程
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
線程池可以高效的執行大量的小任務:Fork/Join線程可以執行一種特殊的任務:1. 可以把一個大任務拆成多個小任務并行的執行2. Fork/Join是在JDK1.7
例如我們計算一個大數組的和:假設有一千萬個元素
我們就可以進行并行計算,然后把兩個結果加起來就是最終的結果.
如果拆成兩個數組以后,每個數組仍然很大,我們還可以進一步拆分,例如拆分四個,我們就可以讓四核的CPU并行的計算
Fork/Join的任務就是把大任務不斷地拆成小任務需要繼承JDK的RecursiveTask的類,然后復寫compute方法
在compute方法內部我們需要把一個大任務拆分多個任務,然后調用invokeAll()這個方法,同時運行兩個小任務,當兩個任務都運行結束以后,invokeAll才會返回,然后我們通過join方法獲得返回結果,最后我們把兩個結果加起來返回
package com.leon.day05;import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;/*** 求和的任務繼承自RecursiveTask,返回值類型是null類型* @author Leon.Sun**/
class SumTask extends RecursiveTask<Long> {// 我們定義了一個常量,用它來指定我們如何來分解任務static final int THRESHOLD = 500;long[] array;int start;int end;// 當我們創建一個SumTask的時候,我們傳入一個數組,傳入start,endSumTask(long[] array, int start, int end) {this.array = array;this.start = start;this.end = end;}@Overrideprotected Long compute() {// 如果任務足夠小我們就直接進行計算if (end - start <= THRESHOLD) {// 如果任務足夠小,直接計算long sum = 0;for (int i = start; i < end; i++) {sum += this.array[i];try {// 在求和的時候我們使用Thread.sleep()中斷兩毫秒// 這樣我們就可以看到forkJoin執行的時間Thread.sleep(2);} catch (InterruptedException e) {}}// 返回計算的結果return sum;}// 任務太大,一分為二,把它拆成兩個子任務int middle = (end + start) / 2;System.out.println(String.format("split %d~%d ==> %d~%d, %d~%d", start,end, start, middle, middle, end));// 我們就獲得了subTask1和subTask2SumTask subtask1 = new SumTask(this.array, start, middle);SumTask subTask2 = new SumTask(this.array, middle, end);// 緊接著我們調用invokeAll方法,同時執行這兩個子任務invokeAll(subtask1, subTask2);// 然后我們通過join方法獲得兩個子任務的方法Long subresult1 = subtask1.join();Long subresult2 = subTask2.join();// 最后把兩個加起來返回Long result = subresult1 + subresult2;System.out.println("result = " + subresult1 + "+" + subresult2+ " ==> " + result);return result;}
}/*** 在這個例子中,我們對一個大數組進行求和* @author Leon.Sun**/
public class ForkJoinTaskSample {static Random random = new Random(0);static long random() {return random.nextInt(1000);}public static void main(String[] args) throws Exception {// 創建1000個隨機數組成的數組// 創建一個包含1000個元素的隨機數組// 由于這個數組包含了一千個元素,所以我們在不使用forkJoin的時候,它大概需要兩秒鐘的時間,來完成求和long[] array = new long[1000];// 創建一個期望求和的值long expectedSum = 0;for (int i = 0; i < array.length; i++) {array[i] = random();expectedSum += array[i];}System.out.println("Expected sum: " + expectedSum);// fork/join// 緊接著我們創建一個ForkJoinTaskForkJoinTask<Long> task = new SumTask(array, 0, array.length);long startTime = System.currentTimeMillis();// 然后我們通過ForkJoinPool.commonPool獲得一個ForkJoinPool// 然后通過invoke方法執行這個任務Long result = ForkJoinPool.commonPool().invoke(task);long endTime = System.currentTimeMillis();// 我們打印任務執行的時間System.out.println("Fork/join sum: " + result + " in "+ (endTime - startTime));}
}Expected sum: 492164
split 0~1000 ==> 0~500, 500~1000
result = 251591+240573 ==> 492164
Fork/join sum: 492164 in 1088
static final int THRESHOLD = 500;這個是表示拆分的大小 每份都是500Expected sum: 492164
split 0~1000 ==> 0~500, 500~1000
split 500~1000 ==> 500~750, 750~1000
split 0~500 ==> 0~250, 250~500
result = 120306+120267 ==> 240573
result = 127611+123980 ==> 251591
result = 251591+240573 ==> 492164
Fork/join sum: 492164 in 540
Fork/Join在JDK的內部也有一些應用:java.util.Arrays.paralleSort(array);這里就是通過Fork/Join把一個大數組進行并行排序,在多核CPU下就可以大大的提高排序的速度.
1. Fork/Join 是一種基于分治的算法:首先把大任務分解成小任務,然后再合并小任務的結果2. ForkJoinPool線程池可以把一個大任務分拆成小任務并行執行3. 我們實現一個任務類必須繼承自RecursiveTask/RecursiveAction這兩個接口的區別是RecursiveTask有返回值,RecursiveAction沒有返回值4. 我們使用Fork/Join模式可以進行并行計算提高效率
?
總結
以上是生活随笔為你收集整理的Fork_Join - Java多线程编程的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ExecutorService- Fu
- 下一篇: ThreadLocal - Java多线