Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用附加线程以更快的方式确定一个数字是否为素数?_Java_Multithreading_Primes - Fatal编程技术网

Java 如何使用附加线程以更快的方式确定一个数字是否为素数?

Java 如何使用附加线程以更快的方式确定一个数字是否为素数?,java,multithreading,primes,Java,Multithreading,Primes,我有一个素数类的程序。它显示x是否为素数。x是程序中正在分析的数字 程序需要多长时间才能知道答案还有时间。x太大了,需要9秒钟才能知道答案。如何使用更多线程使程序运行得更快?在这种情况下,我很难理解如何实现线程 public class PrimeNumbers { private static int x = 2147483647; public static boolean prime= true; public static void main(String[]

我有一个素数类的程序。它显示x是否为素数。x是程序中正在分析的数字

程序需要多长时间才能知道答案还有时间。x太大了,需要9秒钟才能知道答案。如何使用更多线程使程序运行得更快?在这种情况下,我很难理解如何实现线程

public class PrimeNumbers {
    private static int x = 2147483647;

    public static boolean prime= true;

    public static void main(String[]args){

        long start,  end, elapsetime;
        start= System.currentTimeMillis();

        for(int y=2; y<x; y++){
            if(x % y == 0){
                prime=false;
                System.out.println(y);
                break;
            }
        }

        end = System.currentTimeMillis();

        elapsetime = end - start;
        System.out.println("Prime: " + prime);

        System.out.println(elapsetime+ " mill sec " + (elapsetime / 1000 
            + " seconds."));

    }       
}

我将不考虑您是否有最有效的方法,而将重点放在如何使用更多线程加快当前代码的速度上

您当前遍历2->x中的所有数字,并执行一个简单的测试。提高性能的一种方法可能是将此任务分成Z个块,并启动Z个线程并行执行测试

例如,如果你有两个线程,你会让一个线程检查2->x/2,另一个检查x/2+1->x。如果全局且可能是易失性的标志设置为true,则每个线程都应中断其测试,这将表明另一个线程已对素数进行了反驳。

素数测试效率非常低,在每个小于x的数字上循环。你如何改进它?这个

一个好的算法是AKS测试,或埃拉托斯烯筛。下面的代码实现了wiki文章中的一个算法,它比您发布的测试更有效

public static boolean isPrime(long n) { 

    // http://en.wikipedia.org/wiki/Primality test

    if (n <= 3) return n > 1;
    if (n % 2 == 0 || n % 3 == 0) return false;
    for (int i = 5; i*i <=n; i+=6) {
      if (n % i == 0 || n % (i+2) == 0) return false; 
    }
    return true;
  }
}

如果你对更好的算法感兴趣,Munyari已经提出了一个

忽略下面的示例可以帮助您如何使算法并行执行,即使它是一个愚蠢的算法

我们需要一个实现类似于Runnable的可调用接口的类。它应该得到作业的一部分并进行计算

public class PrimeChecker implements Callable<Boolean> {

    private final long numberToCheck;
    private final long start;
    private final long end;

    public PrimeChecker(long numberToCheck, long start, long end) {
        this.numberToCheck = numberToCheck;
        this.start = start;
        if (end >= numberToCheck) {
            this.end = numberToCheck - 1;
        }else{
            this.end = end;
        }
        System.out.println("A PrimeChecker with start " + start + " and end " + end + " values to check number "
                + numberToCheck);
    }

    @Override
    public Boolean call() throws Exception {
        boolean prime = true;
        long current = start;

        if (current != 2 && (current % 2 == 0)) {
            current = current + 1;
        }

        for (; current < end; current = current + 2) {
            if (numberToCheck % current == 0) {
                prime = false;
                System.out.println("The number " + numberToCheck + " is divisable with " + current);
                return prime;
            }
        }
        return prime;
    }

} 
您可以尝试使用不同数量的线程查看numberOfThreads变量以查看差异


我希望这是一个有用的例子,让你更好地理解多线程。小心:它只是整个线程主题的一小部分

如果您不需要自己实现基本检查,我建议使用API。您可以根据自己的需要控制确定性。在本例中为:1-1/2100

编辑 以下是建议示例的优化版本

public class PrimeNumbers {
    private static int x = 2147483647;
    public static boolean prime= true;

    public static void main(String[]args){

        long start, end, elapsetime;
        int divisor = 1;

        start= System.currentTimeMillis();

        if (x % 2 == 0) {
            prime = false;
            divisor = 2;
        } else {
            // - you can use an increment of two
            // because you don't need to check
            // for a divisor which is a multiple
            // of two
            // - you don't need to check for any divisor
            // which is greater than x/2
            for(int y=3; y < x/2; y += 2){
                if(x % y == 0){
                    prime=false;
                    divisor = y;
                    break;
                }
            }
        }

        end = System.currentTimeMillis();

        System.out.println("Prime: " + prime);
        if (!prime) {
            System.out.println("divisible by: " + divisor);
        }

        elapsetime = end - start;
        System.out.println(elapsetime+ " mill sec " + (elapsetime / 1000
            + " seconds."));
    }
}

您可以做许多改进,使其运行得更快,但这些改进不包括多线程。您可能希望得到更好的算法。@Kon为什么?多线程也有帮助。@talex高效多线程确定性素性测试非常复杂,虽然这里有很多非常简单的算法可以改进,但是一个简单的语句可以提高渐进复杂性,这里应该使用什么算法呢?这只是另一个建议,当标志变为true时,你可以杀死所有其他线程,只说不是质数。您不需要等到整个处理完成@Stackflow这就是我所说的每个线程都应该从测试中中断,如果一个全局线程。。。标志被设置为true。@user3802633为什么不根据我的描述自己做呢?有很多资源介绍如何执行多线程。如果你被卡住了,请再发一个问题。这不是AKS的素性测试。测试显示的是一个不错的简单的试算法,适合小数字,可能对原始问题也有好处。关于其他建议,AKS是一种糟糕的方法,实际上它非常慢,SoE用于生成素数,而不是确定单个输入的素数。如果您希望在更大的输入方面比试用版有更好的性能,我建议BPSW或M-R测试对于64位数字都是确定性的。谢谢您的回答。但我真的需要使用线程。不可能吗你说的真线是什么意思?解决方案实际上使用多线程。我不能使用flag或turn来加快进程吗?Hi@user3802633,如果可以存储到int变量中的素数满足您的需要,那么您可以优化代码,例如,如我的第二个代码示例所示。其他优化仍有可能。
public static void main(String[] args) {
    BigInteger mersenne = new BigInteger("2").pow(521).add(BigInteger.ONE.negate());
    System.out.println("digits of the number: " + mersenne.toString().length());

    long start = System.currentTimeMillis();
    final int certainty = 100;
    boolean isPrime = mersenne.isProbablePrime(certainty);
    System.out.println("elapsed millis: " + (System.currentTimeMillis() - start));
    System.out.println("isPrime       : " + isPrime);
}
public class PrimeNumbers {
    private static int x = 2147483647;
    public static boolean prime= true;

    public static void main(String[]args){

        long start, end, elapsetime;
        int divisor = 1;

        start= System.currentTimeMillis();

        if (x % 2 == 0) {
            prime = false;
            divisor = 2;
        } else {
            // - you can use an increment of two
            // because you don't need to check
            // for a divisor which is a multiple
            // of two
            // - you don't need to check for any divisor
            // which is greater than x/2
            for(int y=3; y < x/2; y += 2){
                if(x % y == 0){
                    prime=false;
                    divisor = y;
                    break;
                }
            }
        }

        end = System.currentTimeMillis();

        System.out.println("Prime: " + prime);
        if (!prime) {
            System.out.println("divisible by: " + divisor);
        }

        elapsetime = end - start;
        System.out.println(elapsetime+ " mill sec " + (elapsetime / 1000
            + " seconds."));
    }
}