多线程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-100找到质数,每次找到后通知消费者线程,然后等待消费者处理完成再继续。
- 消费者线程:等待生产者的通知,收到通知后把质数存入数组,然后通知生产者继续找下一个。
- 同步逻辑:用
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
相关产品推荐
相关产品推荐

