开发者社区> 问答> 正文

这两个并发实现中哪一个更快更好

我有两种并行生成质数的实现。核心代码来自Stackoverflow中的另一篇文章。

我想知道这些实现中的哪一种是首选,为什么?另外,是否有更好,更快的解决方案呢?

实施1:

import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class PrimeThreads {

    private static int currentPrime = 0;

    public static void main(String[] args) {

        Object lock = new Object();

        Thread primerGenThread = new Thread(() -> {
            String threadName = Thread.currentThread().getName();
            System.out.println("Starting thread: " + threadName);
            int currentPrimeNo = 0;
            synchronized (lock) {
                try {
                    currentPrimeNo = generateNextPrime();
                } catch (InterruptedException e) {

                    e.printStackTrace();
                }
            }
            System.out.println("Prime Number Associated with this thread " + threadName + " is: " + currentPrimeNo);
            System.out.println("Completed thread: " + threadName);
        });

        System.out.println("****This is where the project starts*****");

        Scanner reader = new Scanner(System.in);
        System.out.print("Enter number of threads you want to create: ");
        int n = reader.nextInt();
        reader.close();

        ExecutorService executor = Executors.newFixedThreadPool(n);
        for(int i=1;i<=n; i++) {
            executor.submit(primerGenThread);
        }
        executor.shutdown();
        try {
            executor.awaitTermination(10, TimeUnit.MINUTES);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        System.out.println("****This is where the project ends*****");

    }

    private static int generateNextPrime() throws InterruptedException {

        long startTime = System.nanoTime();

        currentPrime++;
        if (currentPrime < 2) {
            currentPrime = 2;
            return currentPrime;
        }
        for (int i = 2; i < currentPrime; i++) {
            if (currentPrime % i == 0) {
                currentPrime++;
                i = 2;
            } else {
                continue;
            }
        }       

        long endTime = System.nanoTime();
        System.out.println("Time taken: " + (endTime - startTime) + " naoseconds.");
        return currentPrime;
    }

}

实施2:

import java.util.Scanner;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class PrimeAsyncThreads {

    private static int currentPrime = 0;

    public static void main(String[] args) {

        System.out.println("****This is where the project starts*****");

        Scanner reader = new Scanner(System.in);
        System.out.print("Enter number of threads you want to create: ");
        int n = reader.nextInt();
        reader.close();

        ExecutorService executor = Executors.newFixedThreadPool(n);

        for (int i = 1; i <= n; i++) {
            CompletableFuture.supplyAsync(() -> {
                try {
                    return generateNextPrime();
                } catch (InterruptedException e) {

                    e.printStackTrace();
                }
                return n;
            }, executor).thenAccept(s -> System.out.println("Prime Number Associated with this thread "
                    + Thread.currentThread().getName() + " is: " + currentPrime));
        }

        executor.shutdown();

        try {
            executor.awaitTermination(10, TimeUnit.MINUTES);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        System.out.println("****This is where the project ends*****");
    }

    private static int generateNextPrime() throws InterruptedException {

        long startTime = System.nanoTime();

        currentPrime++;
        if (currentPrime < 2) {
            currentPrime = 2;
            return currentPrime;
        }
        for (int i = 2; i < currentPrime; i++) {
            if (currentPrime % i == 0) {
                currentPrime++;
                i = 2;
            } else {
                continue;
            }
        }

        long endTime = System.nanoTime();
        System.out.println("Time taken: " + (endTime - startTime) + " naoseconds.");
        return currentPrime;
    }
}

感谢您的建议和帮助。

编辑:还注意到,第二种实现不能保证每个线程都会得到一个新的素数。在这种情况下,有时多个线程会获得相同的currentPrime变量值。

谢谢。

问题来源:Stack Overflow

展开
收起
montos 2020-03-26 12:18:22 719 0
1 条回答
写回答
取消 提交回答
  • 这些实现之间的主要区别在于它们的执行方式。

    实施1基本上等于顺序执行。使用线程没有优势,因为如何使用同步块。每个线程在生成下一个素数之前都等待上一个线程完成。

    您已经注意到实现2多次计算相同的素数。这是因为没有同步。仅使用计数器currentPrime来进行某种控制,以便在下一个线程中将哪个数字视为素数。

    因此,两种实现方式均不能并行计算素数以产生可行的结果。

    考虑一下例行程序。您使用一个值来确定其是否为质数。该值应该是每个线程进行计算的输入。现在唯一要考虑的是如何使此值线程安全以确保仅使用一次。

    例如,可以通过使用Atomic变量来实现currentPrime。

    另一个改进可以是currentPrime在generateNextPrime()方法之外增加。此方法可以将值作为参数。就像是

    generateNextPrime(currentPrime.incrementAndGet());
    

    回答来源:Stack Overflow

    2020-03-26 12:18:47
    赞同 展开评论 打赏
问答地址:
问答排行榜
最热
最新

相关电子书

更多
如何做小程序性能优化 立即下载
Web服务架构变化及性能优化 立即下载
亿级 PV网站架构实战之性能压榨 立即下载