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

Java ForkJoinPool線程池的使用之并行計算數(shù)組求和實例

 更新時間:2025年05月29日 09:50:49   作者:學(xué)亮編程手記  
這篇文章主要介紹了Java ForkJoinPool線程池的使用之并行計算數(shù)組求和實例,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

Java ForkJoinPool線程池的使用之并行計算數(shù)組求和

package com.zhangxueliang.juc;

import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.RecursiveTask;

public class ForkJoinPoolDemo {
	static int[] nums = new int[1000000];
	static final int MAX_NUM = 50000;
	static Random r = new Random();
	
	static {
		for(int i=0; i<nums.length; i++) {
			nums[i] = r.nextInt(100);
		}
		
		System.out.println("---" + Arrays.stream(nums).sum()); //stream api
	}
	

	static class AddTask extends RecursiveAction {

		int start, end;

		AddTask(int s, int e) {
			start = s;
			end = e;
		}

		@Override
		protected void compute() {

			if(end-start <= MAX_NUM) {
				long sum = 0L;
				for(int i=start; i<end; i++) sum += nums[i];
				System.out.println("from:" + start + " to:" + end + " = " + sum);
			} else {

				int middle = start + (end-start)/2;

				AddTask subTask1 = new AddTask(start, middle);
				AddTask subTask2 = new AddTask(middle, end);
				subTask1.fork();
				subTask2.fork();
			}


		}

	}

	
	static class AddTaskRet extends RecursiveTask<Long> {
		
		private static final long serialVersionUID = 1L;
		int start, end;
		
		AddTaskRet(int s, int e) {
			start = s;
			end = e;
		}

		@Override
		protected Long compute() {
			
			if(end-start <= MAX_NUM) {
				long sum = 0L;
				for(int i=start; i<end; i++) sum += nums[i];
				return sum;
			} 
			
			int middle = start + (end-start)/2;
			
			AddTaskRet subTask1 = new AddTaskRet(start, middle);
			AddTaskRet subTask2 = new AddTaskRet(middle, end);
			subTask1.fork();
			subTask2.fork();
			
			return subTask1.join() + subTask2.join();
		}
		
	}
	
	public static void main(String[] args) throws IOException {
		/*ForkJoinPool fjp = new ForkJoinPool();
		AddTask task = new AddTask(0, nums.length);
		fjp.execute(task);*/

		ForkJoinPoolDemo temp = new ForkJoinPoolDemo();

		ForkJoinPool fjp = new ForkJoinPool();
		AddTaskRet task = new AddTaskRet(0, nums.length);
		fjp.execute(task);
		long result = task.join();
		System.out.println(result);
		
		//System.in.read();
		
	}
}

ForkJoinPool 示例代碼解析

這段代碼演示了 Java 中 ForkJoinPool 框架的使用,展示了兩種不同的任務(wù)分割方式:

  • RecursiveAction(無返回值)
  • RecursiveTask(有返回值)

代碼結(jié)構(gòu)分析

1. 初始化部分

static int[] nums = new int[1000000];  // 創(chuàng)建包含100萬個元素的數(shù)組
static final int MAX_NUM = 50000;     // 任務(wù)分割的閾值
static Random r = new Random();        // 隨機數(shù)生成器

// 靜態(tài)初始化塊:填充數(shù)組并計算總和
static {
    for(int i=0; i<nums.length; i++) {
        nums[i] = r.nextInt(100);  // 每個元素賦值為0-99的隨機數(shù)
    }
    System.out.println("---" + Arrays.stream(nums).sum()); // 使用stream API計算總和作為驗證基準
}

2. RecursiveAction 實現(xiàn)(無返回值)

static class AddTask extends RecursiveAction {
    int start, end;
    
    AddTask(int s, int e) {
        start = s;
        end = e;
    }

    @Override
    protected void compute() {
        if(end-start <= MAX_NUM) {  // 如果任務(wù)足夠小,直接計算
            long sum = 0L;
            for(int i=start; i<end; i++) sum += nums[i];
            System.out.println("from:" + start + " to:" + end + " = " + sum);
        } else {  // 否則分割任務(wù)
            int middle = start + (end-start)/2;
            AddTask subTask1 = new AddTask(start, middle);
            AddTask subTask2 = new AddTask(middle, end);
            subTask1.fork();  // 異步執(zhí)行子任務(wù)
            subTask2.fork();
        }
    }
}

3. RecursiveTask 實現(xiàn)(有返回值)

static class AddTaskRet extends RecursiveTask<Long> {
    int start, end;
    
    AddTaskRet(int s, int e) {
        start = s;
        end = e;
    }

    @Override
    protected Long compute() {
        if(end-start <= MAX_NUM) {  // 如果任務(wù)足夠小,直接計算并返回結(jié)果
            long sum = 0L;
            for(int i=start; i<end; i++) sum += nums[i];
            return sum;
        } 
        
        // 分割任務(wù)
        int middle = start + (end-start)/2;
        AddTaskRet subTask1 = new AddTaskRet(start, middle);
        AddTaskRet subTask2 = new AddTaskRet(middle, end);
        subTask1.fork();  // 異步執(zhí)行子任務(wù)
        subTask2.fork();
        
        return subTask1.join() + subTask2.join();  // 合并子任務(wù)結(jié)果
    }
}

4. 主方法

public static void main(String[] args) throws IOException {
    // 創(chuàng)建ForkJoinPool實例
    ForkJoinPool fjp = new ForkJoinPool();
    
    // 創(chuàng)建有返回值的任務(wù)
    AddTaskRet task = new AddTaskRet(0, nums.length);
    
    // 執(zhí)行任務(wù)
    fjp.execute(task);
    
    // 獲取并打印結(jié)果
    long result = task.join();
    System.out.println(result);
}

關(guān)鍵概念解釋

ForkJoinPool:

  • Java 7引入的線程池實現(xiàn)
  • 使用工作竊取(work-stealing)算法提高并行效率
  • 特別適合分治(divide-and-conquer)算法

RecursiveAction:

  • 用于不返回結(jié)果的任務(wù)
  • 需要實現(xiàn)compute()方法
  • 示例中的AddTask只打印結(jié)果不返回

RecursiveTask:

  • 用于需要返回結(jié)果的任務(wù)
  • 需要實現(xiàn)compute()方法并返回指定類型
  • 示例中的AddTaskRet返回子數(shù)組的和

fork()和join():

  • fork(): 異步安排任務(wù)執(zhí)行
  • join(): 等待任務(wù)完成并獲取結(jié)果

執(zhí)行流程

  1. 初始化一個包含100萬個隨機數(shù)的數(shù)組
  2. 使用Stream API計算總和作為基準
  3. 創(chuàng)建ForkJoinPool
  4. 創(chuàng)建AddTaskRet任務(wù),范圍是整個數(shù)組
  5. 任務(wù)會根據(jù)MAX_NUM閾值(50000)不斷分割,直到足夠小
  6. 小任務(wù)直接計算子數(shù)組和
  7. 合并所有子任務(wù)的結(jié)果得到最終總和
  8. 打印結(jié)果(應(yīng)與Stream API計算的結(jié)果一致)

使用建議

  1. 對于計算密集型任務(wù),F(xiàn)orkJoinPool通常比傳統(tǒng)線程池更高效
  2. 任務(wù)分割的閾值需要合理設(shè)置,太小會導(dǎo)致過多任務(wù)創(chuàng)建開銷,太大會降低并行度
  3. 有返回結(jié)果需求時使用RecursiveTask,否則使用RecursiveAction
  4. 注意join()是阻塞調(diào)用,會等待任務(wù)完成

這段代碼很好地展示了ForkJoin框架的分治思想和使用方法,是并行計算數(shù)組求和的經(jīng)典示例。

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 淺談Java 三種方式實現(xiàn)接口校驗

    淺談Java 三種方式實現(xiàn)接口校驗

    這篇文章主要介紹了淺談Java 三種方式實現(xiàn)接口校驗,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • SpringBoot實現(xiàn)日志鏈路追蹤的項目實踐

    SpringBoot實現(xiàn)日志鏈路追蹤的項目實踐

    在分布式系統(tǒng)中,由于請求的處理過程可能會跨越多個服務(wù),因此,對請求的追蹤變得尤為重要,本文主要介紹了SpringBoot實現(xiàn)日志鏈路追蹤的項目實踐,感興趣的可以了解一下
    2024-03-03
  • java使用mysql預(yù)編譯語句查詢優(yōu)勢及示例詳解

    java使用mysql預(yù)編譯語句查詢優(yōu)勢及示例詳解

    這篇文章主要為大家介紹了java使用mysql預(yù)編譯語句的優(yōu)勢特點及示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-06-06
  • Springboot集成RabbitMQ并驗證五種消息模型

    Springboot集成RabbitMQ并驗證五種消息模型

    RabbitMQ 提供了5種常用消息模型,本文主要介紹了Springboot集成RabbitMQ并驗證五種消息模型,具有一定的參考價值,感興趣的可以了解一下
    2024-03-03
  • RestTemplate在Spring或非Spring環(huán)境下使用精講

    RestTemplate在Spring或非Spring環(huán)境下使用精講

    這篇文章主要為大家介紹了RestTemplate在Spring或非Spring環(huán)境下使用精講,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-03-03
  • 如何解決IDEA沒有新建servlet選項問題

    如何解決IDEA沒有新建servlet選項問題

    這篇文章主要介紹了如何解決IDEA沒有新建servlet選項問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • Struts之logic標(biāo)簽庫詳解

    Struts之logic標(biāo)簽庫詳解

    本文就Struts之logic標(biāo)簽庫進行詳細介紹,需要的朋友可以參考下
    2012-11-11
  • Java中將String類型轉(zhuǎn)換為int類型的幾種常見方法

    Java中將String類型轉(zhuǎn)換為int類型的幾種常見方法

    在java中經(jīng)常會遇到需要對數(shù)據(jù)進行類型轉(zhuǎn)換的場景,這篇文章主要給大家介紹了關(guān)于Java中將String類型轉(zhuǎn)換為int類型的幾種常見方法,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-07-07
  • Springboot整合支付寶支付功能

    Springboot整合支付寶支付功能

    這篇文章主要介紹了Springboot整合支付寶支付功能,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-01-01
  • SpringMVC實現(xiàn)文件下載功能

    SpringMVC實現(xiàn)文件下載功能

    這篇文章主要為大家詳細介紹了SpringMVC實現(xiàn)文件下載功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-03-03

最新評論