多线程在Java多线程中使用BlockingQueue查找素数
我已经用BlockingQueue实现了一个多线程程序来测试一个数字是否为素数
要求是程序将提示用户输入一个数字,然后程序将按升序从2到用户输入的数字打印每个素数
我有3个类:numbernumerirationtask用于初始化阻塞队列包含所有要检查的数字,PrimeRunner用于检查数字是否为素数,PrimeChecker用于主类
数字消费任务。java
package multithread;
import java.util.concurrent.BlockingQueue;
public class NumberEnumerationTask implements Runnable {
private BlockingQueue<Integer> queue;
private Integer maximum;
public static Integer DUMMY = new Integer(0);
public NumberEnumerationTask(BlockingQueue<Integer> queue, Integer maximum) {
this.queue = queue;
this.maximum = maximum;
}
@Override
public void run() {
try {
enumerate();
queue.put(DUMMY);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* Create a BlockingQueue contain Integer number from 1 to maximum.
* @throws InterruptedException
*/
private void enumerate() throws InterruptedException {
for (int i = 2; i < maximum; i++) {
queue.put(i);
}
}
}
PrimeRunner。java
package multithread;
import java.util.concurrent.BlockingQueue;
public class PrimeRunner implements Runnable {
private BlockingQueue<Integer> queue;
public PrimeRunner(BlockingQueue<Integer> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
boolean done = false;
while (!done) {
Integer checkNumber = queue.take();
if (checkNumber == NumberEnumerationTask.DUMMY) {
queue.put(checkNumber);
done = true;
} else {
checkPrimeNumber(checkNumber);
}
}
} catch(InterruptedException e) {
e.printStackTrace();
}
}
private void checkPrimeNumber(Integer number) {
boolean isPrime = true;
for (int i = 2; i <= number / 2; i++) {
if (number % i == 0) {
isPrime = false;
queue.remove(number);
break;
}
}
if (isPrime == true) {
System.out.print(number + " ");
queue.remove(number);
}
}
}
PrimeChecker。java
public class PrimeChecker {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter maximum number to check: ");
Integer number = sc.nextInt();
BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(number);
NumberEnumerationTask initialize = new NumberEnumerationTask(queue, number);
new Thread(initialize).start();
for (int i = 0; i <= number; i++) {
new Thread(new PrimeRunner(queue)).start();
}
sc.close();
}
}
虚拟变量表示完成
当我运行程序时,有时它不是按升序打印的,有时它是按升序打印的
Enter maximum number to check: 100
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Enter maximum number to check: 100
2 3 5 7 11 13 17 19 23 29 31 41 43 47 37 59 61 53 67 71 73 79 83 89 97
有人能告诉我我的代码有什么问题吗?谢谢
# 1 楼答案
在
PrimeChecker
中,以下代码是原因:您可以创建多个
PrimeRunner
实例,并为每个实例创建一个线程,因此可能会发生如下情况:如果你运行一个
PrimeRunner
,你可以避免这种情况,它会像你预期的那样工作。 如果您仍然想通过synchronized
块运行多个PrimeRunner
围绕以下部分,并且静态字段为PrimeRunner
的对象应该解决这个问题:# 2 楼答案
线程安全是主要问题。在您的代码中,队列在没有任何同步机制的线程之间共享,因此可能会发生数据损坏,从而导致不可预测的结果。如果运行多次,可能会得到不同的结果
多线程可用于基本检查,以加快主要目标的实现,即通过将大数N拆分为多个部分来实现基本查找,单个线程将处理这些部分,一个线程将聚合结果