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

多线程notify与wait()概念解析及质数数组存储代码故障排查求助

问题排查:多线程wait/notify误用导致质数数组存储异常

哥们,我仔细看了你的代码,发现你对多线程里的wait()和notify()理解有点偏差,再加上数组存储的逻辑错误,才导致程序运行异常。咱们一步步拆解问题:

核心问题:wait/notify的使用场景完全错了

wait()和notify()是不同线程之间用来同步的机制——一个线程调用wait()挂起等待,另一个线程调用notify()唤醒它。但你现在把所有代码都塞在同一个线程的synchronized块里,自己调用notify()之后马上wait(),这会导致当前线程直接挂起,而且没有其他线程来唤醒它,程序直接卡死在这里,根本没法继续执行。

其他明显的逻辑错误

除了多线程的误用,你的质数存储逻辑也有问题:

  • 数组越界:primenumber的长度是20,索引范围是0-19,但你写了for (int ab = 0; ab <= 20; ab++),循环到20的时候访问primenumber[20]直接抛出数组越界异常。
  • 存储逻辑错误:每次找到质数,你把数组的所有位置都赋值成当前的i,最后数组里全是最后一个质数,完全达不到“存储所有质数”的目的。

如果你确实想用多线程实现(生产者-消费者模式)

如果一定要用wait()和notify()来练手,我们可以把“找质数”和“存数组”分成两个独立线程,用共享变量和同步机制来配合:

public class PrimeNumberThread {
    // 共享变量:质数数组、当前存储索引、当前找到的质数、是否停止的标志
    private int[] primeNumbers = new int[20];
    private int currentIndex = 0;
    private int currentPrime = -1;
    private boolean isStopped = false;

    // 生产者线程:找质数
    class PrimeFinderThread extends Thread {
        @Override
        public void run() {
            synchronized (PrimeNumberThread.this) {
                System.out.println("The prime numbers are : ");
                for (int i = 2; i <= 100; i++) { // 质数从2开始,1不是质数
                    int count = 0;
                    for (int num = 1; num <= i; num++) {
                        if (i % num == 0) {
                            count++;
                        }
                    }
                    if (count == 2) { // 找到质数
                        currentPrime = i;
                        System.out.print(currentPrime + " ");
                        PrimeNumberThread.this.notify(); // 通知消费者线程存储
                        try {
                            // 等待消费者存储完成,再继续找下一个质数
                            while (currentPrime != -1) { // 确保消费者已经处理完当前质数
                                PrimeNumberThread.this.wait();
                            }
                        } catch (InterruptedException e) {
                            Thread.currentThread().interrupt();
                        }
                    }
                }
                isStopped = true;
                PrimeNumberThread.this.notify(); // 最后通知消费者线程结束
            }
        }
    }

    // 消费者线程:存数组
    class PrimeStorageThread extends Thread {
        @Override
        public void run() {
            synchronized (PrimeNumberThread.this) {
                while (!isStopped) {
                    try {
                        // 等待生产者找到质数或者结束
                        while (currentPrime == -1 && !isStopped) {
                            PrimeNumberThread.this.wait();
                        }
                        if (isStopped) {
                            break;
                        }
                        // 存储质数到数组
                        if (currentIndex < primeNumbers.length) {
                            primeNumbers[currentIndex++] = currentPrime;
                            currentPrime = -1; // 标记已处理
                            PrimeNumberThread.this.notify(); // 通知生产者继续找
                        }
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
                // 打印存储后的数组
                System.out.println("\nStored prime numbers in array:");
                for (int num : primeNumbers) {
                    if (num != 0) {
                        System.out.print(num + " ");
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        PrimeNumberThread demo = new PrimeNumberThread();
        demo.new PrimeFinderThread().start();
        demo.new PrimeStorageThread().start();
    }
}

代码解释:

  1. 生产者线程:负责遍历1-100找到质数,每次找到后通知消费者线程,然后等待消费者处理完成再继续。
  2. 消费者线程:等待生产者的通知,收到通知后把质数存入数组,然后通知生产者继续找下一个。
  3. 同步逻辑:用currentPrime标记当前待存储的质数,用isStopped标记生产者是否完成遍历,确保两个线程之间的协作有序。

如果不需要多线程(更简单的实现)

其实这个需求完全不需要多线程,单线程就能轻松搞定,逻辑更清晰:

public class PrimeNumberSingleThread {
    public static void main(String[] args) {
        int[] primeNumbers = new int[20];
        int index = 0;
        System.out.println("The prime numbers are : ");
        for (int i = 2; i <= 100; i++) {
            boolean isPrime = true;
            for (int num = 2; num <= Math.sqrt(i); num++) { // 优化质数判断逻辑
                if (i % num == 0) {
                    isPrime = false;
                    break;
                }
            }
            if (isPrime && index < primeNumbers.length) {
                primeNumbers[index++] = i;
                System.out.print(i + " ");
            }
        }
        // 打印数组
        System.out.println("\nStored prime numbers in array:");
        for (int num : primeNumbers) {
            if (num != 0) {
                System.out.print(num + " ");
            }
        }
    }
}

这个版本不仅逻辑简单,还优化了质数判断的效率(只需要遍历到sqrt(i)),完全能满足你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:27:08