欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java分治思想之ForkJoin詳解

 更新時(shí)間:2023年04月27日 10:36:29   作者:碼下客  
這篇文章主要為大家介紹了java分治思想之ForkJoin使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

前言

  當(dāng)我們面對(duì)需要同時(shí)執(zhí)行多個(gè)任務(wù)的情況時(shí),往往需要耗費(fèi)大量的時(shí)間和精力來編寫復(fù)雜的并發(fā)代碼。但是有一種技術(shù)可以幫助我們輕松地處理這種情況。通過forkJoin,我們可以簡單地實(shí)現(xiàn)多個(gè)任務(wù)的并行執(zhí)行,從而提高應(yīng)用程序的性能和響應(yīng)能力。在本文中,我們將深入探討forkJoin的工作原理和使用方法。

分治思想算法

  fork-join模式是基于分治思想的并行計(jì)算模式之一。該模式將一個(gè)大的任務(wù)分割成多個(gè)小的子任務(wù),然后并行執(zhí)行這些子任務(wù),最后將它們的結(jié)果合并起來得到最終的結(jié)果。在這個(gè)過程中,每個(gè)子任務(wù)的執(zhí)行可以進(jìn)一步分解為更小的子任務(wù),直到達(dá)到某個(gè)閾值,這時(shí)候任務(wù)將被串行執(zhí)行。這種遞歸的分治思想使得fork-join模式可以有效地利用計(jì)算機(jī)的多核處理能力,從而提高程序的性能和效率。

歸并排序

歸并排序是一種基于分治思想的排序算法。其核心思想是將一個(gè)數(shù)組分成兩個(gè)子數(shù)組,分別對(duì)其進(jìn)行排序后再將其合并起來。具體實(shí)現(xiàn)過程如下:

  • 分解:將一個(gè)數(shù)組分成兩個(gè)子數(shù)組,分別對(duì)其進(jìn)行排序??梢允褂眠f歸來實(shí)現(xiàn)這一步驟。
  • 合并:將排序后的兩個(gè)子數(shù)組合并成一個(gè)有序的數(shù)組。
  • 遞歸:對(duì)兩個(gè)子數(shù)組遞歸進(jìn)行分解和排序,直到每個(gè)子數(shù)組的長度為1。

時(shí)間復(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ù)組第一個(gè)元素
     * @param right 數(shù)組最后一個(gè)元素
     */
    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ù)組第一個(gè)元素
     * @param mid 數(shù)組分割的元素
     * @param right 數(shù)組最后一個(gè)元素
     */
    public static void merge(int[] arr,int left,int mid,int right){
        //創(chuàng)建臨時(shí)數(shù)組,用于存放合并后的數(shù)組
        int[] temp = new int[right - left + 1];
        //左面數(shù)組的起始指針
        int i = left;
        //右面數(shù)組的起始指針
        int j = mid + 1;
        //臨時(shí)數(shù)組的下標(biāo)
        int k = 0;
        //數(shù)組左面和數(shù)組右面都還有值就去遍歷比較賦值
        while (i <= mid && j <= right) {
            //數(shù)組左面的值小于或者等于數(shù)組右面的值就把左面的值賦值到臨時(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ù)組中的元素拷貝會(huì)回原數(shù)組中
        for (int p = 0; p < temp.length; p++) {
            arr[left + p] = temp[p];
        }
    }
}

快速排序

快速排序(Quick Sort)是一種基于分治思想的排序算法,它采用了遞歸的方式將一個(gè)大的數(shù)組分解成多個(gè)子數(shù)組,分別進(jìn)行排序后再將它們合并起來。其基本思想是選取一個(gè)基準(zhǔn)元素,將數(shù)組中小于該元素的值放在左邊,大于該元素的值放在右邊,然后遞歸地對(duì)左右兩個(gè)子數(shù)組進(jìn)行排序。具體的步驟如下:

  • 選取一個(gè)基準(zhǔn)元素(通常是數(shù)組中的第一個(gè)元素)。
  • 將數(shù)組中小于該元素的值放在左邊,大于該元素的值放在右邊。
  • 對(duì)左右兩個(gè)子數(shù)組分別遞歸進(jìn)行快速排序。
  • 合并左右兩個(gè)已排序的子數(shù)組。

快速排序的時(shí)間復(fù)雜度為O(nlogn),它是一種原地排序算法,不需要額外的存儲(chǔ)空間,因此空間復(fù)雜度為O(1)。雖然快速排序的最壞時(shí)間復(fù)雜度為O(n^2),但是在實(shí)際應(yīng)用中,快速排序的平均時(shí)間復(fù)雜度和最好時(shí)間復(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){
        //取第一個(gè)元素為基準(zhǔn)元素
        int pivot = arr[left];
        int i = left+1;
        int j = right;
        while (i<=j){
            //當(dāng)前指針位置數(shù)小于基準(zhǔn)元素就繼續(xù)移動(dòng)指針直到遇到大的
            while (i<=j && arr[i] < pivot){
                i++;
            }
            //當(dāng)前指針位置數(shù)大于基準(zhǔn)元素就繼續(xù)移動(dòng)指針直到遇到小的
            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是一個(gè)線程池,它用于管理ForkJoin任務(wù)的執(zhí)行。ForkJoinTask是一個(gè)抽象類,用于表示可以被分割成更小部分的任務(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)先級(jí)、任務(wù)隊(duì)列的容量等,可以根據(jù)具體的應(yīng)用場(chǎng)景進(jìn)行設(shè)置。

構(gòu)造器

ForkJoinPool中有四個(gè)核心參數(shù),用于控制線程池的并行數(shù)、工作線程的創(chuàng)建、異常處理和模式指定等。

  • int parallelism:指定并行級(jí)別(parallelism level)。ForkJoinPool將根據(jù)這個(gè)設(shè)定,決定工作線程的數(shù)量。如果未設(shè)置的話,將使用Runtime.getRuntime().availableProcessors()來設(shè)置并行級(jí)別;
  • ForkJoinWorkerThreadFactory factory:ForkJoinPool在創(chuàng)建線程時(shí),會(huì)通過factory來創(chuàng)建。注意,這里需要實(shí)現(xiàn)的是ForkJoinWorkerThreadFactory,而不是ThreadFactory。如果你不指定factory,那么將由默認(rèn)的 DefaultForkJoinWorkerThreadFactory負(fù)責(zé)線程的創(chuàng)建工作;
  • UncaughtExceptionHandler handler:指定異常處理器,當(dāng)任務(wù)在運(yùn)行中出錯(cuò)時(shí),將由設(shè)定的處理器處理;
  • boolean asyncMode:設(shè)置隊(duì)列的工作模式。當(dāng)asyncMode為true時(shí),將使用先進(jìn)先出隊(duì)列,而為false時(shí)則使用后進(jìn)先出的模式。

工作竊取法

在Fork-Join模式中,任務(wù)被分配給一個(gè)線程池中的工作線程來執(zhí)行。當(dāng)一個(gè)工作線程執(zhí)行完自己分配的任務(wù)后,它可以從其他工作線程的任務(wù)隊(duì)列中偷取(Steal)任務(wù)來執(zhí)行,這就是所謂的工作竊?。╓ork 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的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論