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

如何不使用Callable调用ArrayList<Thread>中Runnable的getter获取tempCounter?

不用Callable获取Runnable计算结果的解决方案

嘿,我来帮你捋清楚这个问题~你遇到的“符号未找到”错误,以及想调用ArrayList内Runnable方法的需求,其实都可以通过自定义子类或者线程安全的共享变量来解决,下面给你详细拆解:

为什么直接访问tempCounter会报错?

你收到“符号未找到”错误,大概率是这两个原因:

  • 你的primeThread里的tempCounter是私有变量,外部类PrimeCounter没有访问权限;
  • 如果primeThread是匿名Runnable或者lambda表达式,编译器只会把它当成Runnable接口实例,而接口里并没有tempCounter这个成员,自然找不到对应的符号。

不用Callable,怎么获取Runnable的计算结果?

这里有两种实用的方案:

方案1:自定义Runnable子类,提供getter方法

自己写一个继承自Runnable的类,把计算结果存在成员变量里,再写一个getter方法让外部获取:

// 自定义PrimeRunnable类
class PrimeRunnable implements Runnable {
    private int tempCounter; // 存储当前线程的质数统计结果

    @Override
    public void run() {
        // 这里写你的质数计算逻辑,把统计结果赋值给tempCounter
        tempCounter = 0;
        for (int i = 2; i < 100; i++) {
            if (isPrime(i)) {
                tempCounter++;
            }
        }
    }

    // 提供getter方法,让外部获取计算结果
    public int getTempCounter() {
        return tempCounter;
    }

    // 辅助方法:判断是否为质数
    private boolean isPrime(int num) {
        if (num <= 1) return false;
        for (int i = 2; i <= Math.sqrt(num); i++) {
            if (num % i == 0) return false;
        }
        return true;
    }
}

然后在PrimeCounter里,必须等待线程执行完毕后,再通过getter拿结果累加:

public class PrimeCounter {
    public static void main(String[] args) throws InterruptedException {
        int counter = 0;
        List<PrimeRunnable> threadList = new ArrayList<>();

        // 创建并启动多个PrimeRunnable线程
        for (int i = 0; i < 4; i++) {
            PrimeRunnable runnable = new PrimeRunnable();
            threadList.add(runnable);
            new Thread(runnable).start();
        }

        // 等待所有线程完成,再累加结果
        for (PrimeRunnable runnable : threadList) {
            runnable.join(); // 等待当前线程执行完
            counter += runnable.getTempCounter();
        }

        System.out.println("总质数数量:" + counter);
    }
}

⚠️ 注意:一定要调用join(),不然线程还没跑完就去拿tempCounter,得到的会是初始值0或者不正确的结果。

方案2:用线程安全的共享变量直接累加

如果不想写自定义Runnable子类,可以用AtomicInteger这种线程安全的原子类,让每个线程直接把计算结果加到共享变量里:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class PrimeCounter {
    public static void main(String[] args) throws InterruptedException {
        AtomicInteger totalCounter = new AtomicInteger(0);
        List<Thread> threadList = new ArrayList<>();

        for (int i = 0; i < 4; i++) {
            Thread thread = new Thread(() -> {
                int temp = 0;
                // 质数计算逻辑
                for (int num = 2; num < 100; num++) {
                    if (isPrime(num)) {
                        temp++;
                    }
                }
                // 原子性地把temp加到总计数器里
                totalCounter.addAndGet(temp);
            });
            threadList.add(thread);
            thread.start();
        }

        // 等待所有线程完成
        for (Thread thread : threadList) {
            thread.join();
        }

        System.out.println("总质数数量:" + totalCounter.get());
    }

    private static boolean isPrime(int num) {
        if (num <= 1) return false;
        for (int i = 2; i <= Math.sqrt(num); i++) {
            if (num % i == 0) return false;
        }
        return true;
    }
}

这种方法不用事后去每个线程里拿结果,直接在计算完后自动累加,还避免了多线程环境下的竞态问题。

能不能在PrimeCounter中调用ArrayList内的Runnable方法?

当然可以,但有个前提:你的Runnable必须是自定义的子类实例,而不是匿名内部类或者lambda。因为如果是lambda/匿名Runnable,编译器只认为它是Runnable接口的实现,而接口里只有run()方法,你没法调用自定义的方法。

举个例子,如果你的ArrayList里存的是PrimeRunnable实例,但声明的是ArrayList<Runnable>,那需要先强转类型再调用方法:

ArrayList<Runnable> runnables = new ArrayList<>();
runnables.add(new PrimeRunnable());

// 遍历调用自定义方法
for (Runnable r : runnables) {
    if (r instanceof PrimeRunnable) {
        int count = ((PrimeRunnable) r).getTempCounter();
        // 处理count
    }
}

不过更规范的做法是直接把ArrayList的泛型声明为ArrayList<PrimeRunnable>,这样就不用强转,代码更安全。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:59:45