简体   繁体   English

在Java中使用BlockingQueue在多线程中查找素数

[英]Finding prime number using BlockingQueue in Java with multi threading

I've implemented a multi thread program using BlockingQueue to test for a number is prime or not. 我使用BlockingQueue实现了一个多线程程序,以测试数字是否为质数。

The requirement is the program will prompt user to input a number and then the program will print every prime number from 2 to inputted number from user in ascending order. 要求是程序将提示用户输入数字,然后程序将按升序打印每个从2到用户输入数字的素数。

I have 3 class: NumberEnumerationTask for initialize BlockingQueue contains all numbers to be check, PrimeRunner for check the number is prime or not, PrimeChecker for the main class. 我有3类:NumberEnumerationTask用于初始化的BlockingQueue包含了所有的数字是检查,PrimeRunner为检查号是质不是,PrimeChecker主类。

NumberEnumerationTask.java NumberEnumerationTask.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 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 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();
    }
}

The DUMMY variable is to signal completion. DUMMY变量用于表示完成。

When I run the program, sometime it's not print in ascending order, sometime it does. 当我运行该程序时,有时它不是按升序打印的,有时是的。

Enter maximum number to check: 100 输入要检查的最大数字: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 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 输入要检查的最大数字: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 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

Can someone tell me what is wrong with my code? 有人可以告诉我我的代码有什么问题吗? Thanks 谢谢

In PrimeChecker , the following code is the cause: PrimeChecker ,以下代码是原因:

for (int i = 0; i <= number; i++) {
    new Thread(new PrimeRunner(queue)).start();
}

You create multiple PrimeRunner instances and a thread for each of them, so something like below can happen: 您创建了多个PrimeRunner实例以及每个实例的一个线程,因此可能会发生以下情况:

  1. PrimeRunner in thread 1 takes 5. 线程1中的PrimeRunner需要5。
  2. PrimeRunner in thread 2 takes 7. 线程2中的PrimeRunner需要7。
  3. PrimeRunner in thread 2 prints 7. (PrimeRunner in thread 1 is still checking...) 线程2中的PrimeRunner打印7。(线程1中的PrimemeRunner仍在检查...)
  4. PrimeRunner in thread 1 prints 5. 线程1中的PrimeRunner打印5。

If you run a single PrimeRunner you can avoid such cases and it works as you expected. 如果只运行一个PrimeRunner ,则可以避免这种情况,并且可以按预期运行。 If you still want to run multiple PrimeRunner surrounding the following part by synchronized block with an object in a static field of PrimeRunner should solve the problem: 如果您仍然想通过与PrimeRunner静态字段中的对象进行synchronizedPrimeRunner围绕以下部分运行多个PrimeRunnerPrimeRunner应该可以解决该问题:

Integer checkNumber = queue.take();
if (checkNumber == NumberEnumerationTask.DUMMY) {
    queue.put(checkNumber);
    done = true;
} else {
    checkPrimeNumber(checkNumber);
}

Thread safety is the major issue. 线程安全是主要问题。 In your code, queue is shared among threads which is being processed without any synchronization mechanism hence data corruption likely to happen hence unpredictable result. 在您的代码中,队列在正在处理的线程之间共享,没有任何同步机制,因此可能会发生数据损坏,从而导致不可预测的结果。 If you run it multiple times you might get different results. 如果多次运行它,可能会得到不同的结果。

Multi-threading could be used for prime check to speed up the main goal ie prime finding which could be achieved by splitting the big number N into multiple parts and individual thread would work upon these parts and one thread to aggregate the results. 多线程可用于素数检查以加快主要目标,即可以通过将大数N拆分为多个部分来实现素数查找,并且单个线程将在这些部分上工作,而一个线程将结果汇总。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM