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

Thread类无法更新调用类的共享数组问题求助

多线程实现productExceptSelf结果全为0的问题排查与修复

核心问题分析

  1. 静态nums变量未赋值
    Solution类中定义了静态nums数组,但在productExceptSelf方法里,仅接收了方法参数nums,并未将其赋值给静态变量。Threaded类的run方法调用getProduct(nums, i)时,此处的nums是未初始化的静态变量(值为null),导致getProduct方法中访问nums.length抛出NullPointerException,线程异常终止,无法修改answer数组,最终answer保持初始的全0状态。

  2. 线程等待逻辑不可靠
    使用while(threadgrp.activeCount() > 0)的忙等方式存在缺陷:activeCount()返回的是线程组活跃线程的估计值,无法保证准确性,可能导致主线程提前退出,子线程尚未完成计算。

  3. 冗余参数与变量作用域问题
    Threaded类的getProduct方法接收了nums参数,但实际调用时传入的是未初始化的静态nums,参数本身冗余且容易引发混淆。

修复方案

方案1:移除静态变量,改用内部类捕获外部变量(推荐)

避免静态变量带来的线程安全和作用域问题,直接在子线程中使用方法参数nums,同时用join()等待所有线程完成:

class Solution {
    public int[] productExceptSelf(int[] nums) {
        int n = nums.length;
        int[] answer = new int[n];
        Thread[] threads = new Thread[n];

        for (int i = 0; i < n; i++) {
            final int idx = i; // 保证lambda中变量有效final
            threads[i] = new Thread(() -> {
                int product = 1;
                for (int j = 0; j < n; j++) {
                    if (j != idx) {
                        product *= nums[j];
                    }
                }
                answer[idx] = product;
            });
            threads[i].start();
        }

        // 等待所有子线程执行完成
        for (Thread thread : threads) {
            try {
                thread.join();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException("线程被中断", e);
            }
        }

        return answer;
    }
}

方案2:修正静态变量赋值与线程等待逻辑

如果坚持使用独立的Threaded类,需确保静态变量正确赋值,并改用可靠的线程等待方式:

class Solution {
    public static int[] nums;
    public static int[] answer;

    public int[] productExceptSelf(int[] inputNums) {
        nums = inputNums; // 给静态nums赋值
        int n = nums.length;
        answer = new int[n];
        Thread[] threads = new Thread[n];

        for (int i = 0; i < n; i++) {
            threads[i] = new Threaded(i);
            threads[i].start();
        }

        // 等待所有线程完成
        for (Thread t : threads) {
            try {
                t.join();
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                throw new RuntimeException(e);
            }
        }

        return answer;
    }
}

class Threaded extends Thread {
    int i;

    Threaded(int i) {
        this.i = i;
    }

    @Override
    public void run() {
        answer[i] = getProduct();
    }

    private int getProduct() {
        int x = 1;
        for (int j = 0; j < Solution.nums.length; j++) {
            if (i != j) {
                x *= Solution.nums[j];
            }
        }
        return x;
    }
}

额外建议:多线程并非最优解

你最初用多线程是为了解决单线程超时问题,但实际上productExceptSelf存在时间复杂度O(n)、空间复杂度O(1)(除输出数组)的最优解法,比多线程更高效,完全不会超时:

class Solution {
    public int[] productExceptSelf(int[] nums) {
        int n = nums.length;
        int[] answer = new int[n];
        
        // 计算前缀乘积:answer[i]是nums[0..i-1]的乘积
        answer[0] = 1;
        for (int i = 1; i < n; i++) {
            answer[i] = answer[i-1] * nums[i-1];
        }
        
        // 计算后缀乘积并合并:suffix是nums[i+1..n-1]的乘积
        int suffix = 1;
        for (int i = n-1; i >= 0; i--) {
            answer[i] *= suffix;
            suffix *= nums[i];
        }
        
        return answer;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 19:07:38