java分治思想之ForkJoin詳解
前言
當(dāng)我們面對需要同時執(zhí)行多個任務(wù)的情況時,往往需要耗費大量的時間和精力來編寫復(fù)雜的并發(fā)代碼。但是有一種技術(shù)可以幫助我們輕松地處理這種情況。通過forkJoin,我們可以簡單地實現(xiàn)多個任務(wù)的并行執(zhí)行,從而提高應(yīng)用程序的性能和響應(yīng)能力。在本文中,我們將深入探討forkJoin的工作原理和使用方法。
分治思想算法
fork-join模式是基于分治思想的并行計算模式之一。該模式將一個大的任務(wù)分割成多個小的子任務(wù),然后并行執(zhí)行這些子任務(wù),最后將它們的結(jié)果合并起來得到最終的結(jié)果。在這個過程中,每個子任務(wù)的執(zhí)行可以進(jìn)一步分解為更小的子任務(wù),直到達(dá)到某個閾值,這時候任務(wù)將被串行執(zhí)行。這種遞歸的分治思想使得fork-join模式可以有效地利用計算機(jī)的多核處理能力,從而提高程序的性能和效率。
歸并排序
歸并排序是一種基于分治思想的排序算法。其核心思想是將一個數(shù)組分成兩個子數(shù)組,分別對其進(jìn)行排序后再將其合并起來。具體實現(xiàn)過程如下:
- 分解:將一個數(shù)組分成兩個子數(shù)組,分別對其進(jìn)行排序??梢允褂眠f歸來實現(xiàn)這一步驟。
- 合并:將排序后的兩個子數(shù)組合并成一個有序的數(shù)組。
- 遞歸:對兩個子數(shù)組遞歸進(jìn)行分解和排序,直到每個子數(shù)組的長度為1。
時間復(fù)雜度為O(nlogn)。

public class Merge {
public static void main(String[] args) {
int[] arr = { 5, 2, 8, 4, 7, 1, 3, 6 };
mergeSort(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));
}
/**
* 拆分
* @param arr 數(shù)組
* @param left 數(shù)組第一個元素
* @param right 數(shù)組最后一個元素
*/
public static void mergeSort(int[] arr,int left,int right){
if (left < right) {
int mid = (left + right) / 2;
mergeSort(arr, left, mid);
mergeSort(arr, mid + 1, right);
merge(arr, left, mid, right);
}
}
/**
* 合并
* @param arr 數(shù)組
* @param left 數(shù)組第一個元素
* @param mid 數(shù)組分割的元素
* @param right 數(shù)組最后一個元素
*/
public static void merge(int[] arr,int left,int mid,int right){
//創(chuàng)建臨時數(shù)組,用于存放合并后的數(shù)組
int[] temp = new int[right - left + 1];
//左面數(shù)組的起始指針
int i = left;
//右面數(shù)組的起始指針
int j = mid + 1;
//臨時數(shù)組的下標(biāo)
int k = 0;
//數(shù)組左面和數(shù)組右面都還有值就去遍歷比較賦值
while (i <= mid && j <= right) {
//數(shù)組左面的值小于或者等于數(shù)組右面的值就把左面的值賦值到臨時數(shù)組中
//并且把左面的指針和臨時數(shù)組的指針+1
//否則相反
if (arr[i] <= arr[j]) {
temp[k] = arr[i];
k++;
i++;
} else {
temp[k] = arr[j];
k++;
j++;
}
}
//把剩余數(shù)組塞進(jìn)去
while (i <= mid) {
temp[k] = arr[i];
k++;
i++;
}
while (j <= right) {
temp[k] = arr[j];
k++;
j++;
}
//講臨時數(shù)組中的元素拷貝會回原數(shù)組中
for (int p = 0; p < temp.length; p++) {
arr[left + p] = temp[p];
}
}
}
快速排序
快速排序(Quick Sort)是一種基于分治思想的排序算法,它采用了遞歸的方式將一個大的數(shù)組分解成多個子數(shù)組,分別進(jìn)行排序后再將它們合并起來。其基本思想是選取一個基準(zhǔn)元素,將數(shù)組中小于該元素的值放在左邊,大于該元素的值放在右邊,然后遞歸地對左右兩個子數(shù)組進(jìn)行排序。具體的步驟如下:
- 選取一個基準(zhǔn)元素(通常是數(shù)組中的第一個元素)。
- 將數(shù)組中小于該元素的值放在左邊,大于該元素的值放在右邊。
- 對左右兩個子數(shù)組分別遞歸進(jìn)行快速排序。
- 合并左右兩個已排序的子數(shù)組。
快速排序的時間復(fù)雜度為O(nlogn),它是一種原地排序算法,不需要額外的存儲空間,因此空間復(fù)雜度為O(1)。雖然快速排序的最壞時間復(fù)雜度為O(n^2),但是在實際應(yīng)用中,快速排序的平均時間復(fù)雜度和最好時間復(fù)雜度均為O(nlogn),因此是一種非常高效的排序算法

public class QuickSort {
public static void main(String[] args) {
int[] arr = { 5, 2, 8, 4, 7, 1, 3, 6 };
quickSort(arr, 0, arr.length - 1);
System.out.println(Arrays.toString(arr));
}
public static void quickSort(int[] arr,int left,int right){
if(left<right){
int pivotIndex = partition(arr, left, right);
quickSort(arr,left,pivotIndex-1);
quickSort(arr,pivotIndex+1,right);
}
}
public static int partition(int[] arr,int left,int right){
//取第一個元素為基準(zhǔn)元素
int pivot = arr[left];
int i = left+1;
int j = right;
while (i<=j){
//當(dāng)前指針位置數(shù)小于基準(zhǔn)元素就繼續(xù)移動指針直到遇到大的
while (i<=j && arr[i] < pivot){
i++;
}
//當(dāng)前指針位置數(shù)大于基準(zhǔn)元素就繼續(xù)移動指針直到遇到小的
while (i<=j && arr[j] > pivot){
j--;
}
if(i<j){
//交換元素位置
swap(arr,i,j);
i++;
j--;
}
}
//跳出循環(huán)說明i和j相遇,j的值一定是大于基準(zhǔn)元素,要和基準(zhǔn)元素進(jìn)行交換
swap(arr,left,j);
//返回基準(zhǔn)元素位置
return j;
}
public static void swap(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
Fork/Join
Fork/Join框架的主要組成部分是ForkJoinPool、ForkJoinTask。ForkJoinPool是一個線程池,它用于管理ForkJoin任務(wù)的執(zhí)行。ForkJoinTask是一個抽象類,用于表示可以被分割成更小部分的任務(wù)。
ForkJoinPool
ForkJoinPool是Fork/Join框架中的線程池類,它用于管理Fork/Join任務(wù)的線程。ForkJoinPool類包括一些重要的方法,例如submit()、invoke()、shutdown()、awaitTermination()等,用于提交任務(wù)、執(zhí)行任務(wù)、關(guān)閉線程池和等待任務(wù)的執(zhí)行結(jié)果。ForkJoinPool類中還包括一些參數(shù),例如線程池的大小、工作線程的優(yōu)先級、任務(wù)隊列的容量等,可以根據(jù)具體的應(yīng)用場景進(jìn)行設(shè)置。
構(gòu)造器
ForkJoinPool中有四個核心參數(shù),用于控制線程池的并行數(shù)、工作線程的創(chuàng)建、異常處理和模式指定等。
- int parallelism:指定并行級別(parallelism level)。ForkJoinPool將根據(jù)這個設(shè)定,決定工作線程的數(shù)量。如果未設(shè)置的話,將使用Runtime.getRuntime().availableProcessors()來設(shè)置并行級別;
- ForkJoinWorkerThreadFactory factory:ForkJoinPool在創(chuàng)建線程時,會通過factory來創(chuàng)建。注意,這里需要實現(xiàn)的是ForkJoinWorkerThreadFactory,而不是ThreadFactory。如果你不指定factory,那么將由默認(rèn)的 DefaultForkJoinWorkerThreadFactory負(fù)責(zé)線程的創(chuàng)建工作;
- UncaughtExceptionHandler handler:指定異常處理器,當(dāng)任務(wù)在運(yùn)行中出錯時,將由設(shè)定的處理器處理;
- boolean asyncMode:設(shè)置隊列的工作模式。當(dāng)asyncMode為true時,將使用先進(jìn)先出隊列,而為false時則使用后進(jìn)先出的模式。
工作竊取法
在Fork-Join模式中,任務(wù)被分配給一個線程池中的工作線程來執(zhí)行。當(dāng)一個工作線程執(zhí)行完自己分配的任務(wù)后,它可以從其他工作線程的任務(wù)隊列中偷?。⊿teal)任務(wù)來執(zhí)行,這就是所謂的工作竊取(Work Stealing)。
使用
public class SumTask extends RecursiveTask<Integer> {
private static final int THRESHOLD = 1000;
private int[] array;
private int start;
private int end;
public SumTask(int[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
if (end - start <= THRESHOLD) {
int sum = 0;
for (int i = start; i < end; i++) {
sum += array[i];
}
return sum;
} else {
int mid = (start + end) / 2;
SumTask leftTask = new SumTask(array, start, mid);
SumTask rightTask = new SumTask(array, mid, end);
leftTask.fork();
rightTask.fork();
int leftResult = leftTask.join();
int rightResult = rightTask.join();
return leftResult + rightResult;
}
}
public static void main(String[] args) {
int[] array = new int[10000];
for (int i = 0; i < array.length; i++) {
array[i] = i + 1;
}
ForkJoinPool forkJoinPool = new ForkJoinPool();
SumTask task = new SumTask(array, 0, array.length);
int result = forkJoinPool.invoke(task);
System.out.println(result);
}
}以上就是java分治思想之ForkJoin詳解的詳細(xì)內(nèi)容,更多關(guān)于java分治思想ForkJoin的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java調(diào)用微信現(xiàn)金紅包接口的心得與體會總結(jié)
這篇文章主要介紹了java調(diào)用微信現(xiàn)金紅包接口的心得與體會總結(jié),有需要的朋友可以了解一下。2016-11-11
Springboot實現(xiàn)ModbusTCP通信的示例詳解
ModbusTCP協(xié)議是Modbus由MODICON公司于1979年開發(fā),是一種工業(yè)現(xiàn)場總線協(xié)議標(biāo)準(zhǔn),本文主要介紹了Springboot實現(xiàn)ModbusTCP通信的相關(guān)知識,需要的可以參考下2023-12-12
mybatis執(zhí)行update批量更新時報錯的解決方案
這篇文章主要介紹了mybatis執(zhí)行update批量更新時報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
Java Web基于Session的登錄實現(xiàn)方法
這篇文章主要介紹了Java Web基于Session的登錄實現(xiàn)方法,涉及Java針對session的操作及表單提交與驗證技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-10-10

