You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java动态线程数下可变长度整型数组的分区并行处理问题

问题诊断

你的代码存在两处核心错误:

  • 任务提交逻辑错误:无论输入数组长度多少,都固定提交threadCount个任务。当数组长度小于线程数时,会产生大量无意义的空任务,这就是你输出中出现大量线程启动日志却没有对应元素输出的原因。
  • 分区计算逻辑错误:当前分区起止计算规则i * threadCount ~ (i+1)*threadCount完全不符合分片逻辑,会引发两个问题:1)大数组场景下分片步长等于线程数,分片粒度不合理;2)分片结束位置大概率超过数组长度,存在ArrayIndexOutOfBoundsException风险。
解决方案

正确的分片逻辑需要同时适配数组长度小于/大于线程数的两种场景,你可以根据业务需求选择以下两种策略:

策略1:最大化并行,小数组每个元素单独分配任务

适合元素处理逻辑是计算密集型的场景,修正后代码如下:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) {
        int threadCount = Runtime.getRuntime().availableProcessors() * 2;
        // 限制线程数范围4~64
        threadCount = Math.max(4, Math.min(64, threadCount));
        ExecutorService executor = Executors.newFixedThreadPool(threadCount);
        final int[] inputArr = new int[]{1, 2, 4, 5};
        int arrLength = inputArr.length;

        // 计算分片基础大小
        int chunkSize = arrLength / threadCount;
        // 数组长度小于线程数时,每个分片1个元素
        chunkSize = chunkSize == 0 ? 1 : chunkSize;
        // 计算实际需要提交的任务数
        int taskCount = (int) Math.ceil((double) arrLength / chunkSize);

        for (int i = 0; i < taskCount; i++) {
            int start = i * chunkSize;
            int end = Math.min((i + 1) * chunkSize, arrLength);
            executor.submit(new Worker(inputArr, start, end));
        }

        executor.shutdown();
        try {
            executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static class Worker implements Runnable {
        private final int[] arr;
        private final int start;
        private final int end;

        public Worker(int[] arr, int startIndex, int endIndex) {
            this.arr = arr;
            this.start = startIndex;
            this.end = endIndex;
        }

        @Override
        public void run() {
            System.out.printf("Thread start: %d\n", Thread.currentThread().getId());
            for (int i = this.start; i < this.end; i++) {
                System.out.println(arr[i]);
            }
            System.out.printf("Thread end: %d\n", Thread.currentThread().getId());
        }
    }
}

策略2:减少线程调度,小数组整个分配给单个任务

适合元素处理逻辑简单、小数组场景下减少线程切换开销,符合你给出的期望输出示例,只需要修改分片计算部分:

// 计算分片基础大小
int chunkSize = arrLength / threadCount;
int taskCount;
if (chunkSize == 0) {
    // 数组长度小于线程数时,只用1个任务处理全量数据
    chunkSize = arrLength;
    taskCount = 1;
} else {
    taskCount = (int) Math.ceil((double) arrLength / chunkSize);
}

内容的提问来源于stack exchange,提问作者max42

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 03:42:03