java - Java中如何使用多线程编写圆周率计算程序?

标签 java multithreading pi approximation

我需要使用 Java 多线程创建一个程序来计算常量 PI 的近似值。

我打算用格雷戈里-莱布尼茨级数计算 PI/4 的结果,然后乘以 4 得到 PI 近似值。

enter image description here

但是我对这个程序有些担心:

  1. 如何将计算过程分开,使程序实现多线程处理?因为公式是求和的,不知道怎么拆分,最后全部凑齐。
  2. 我在考虑程序将无限执行公式这一事实,因此用户需要提供一些配置执行的方法,以确定何时停止并返回结果。这可能吗?我该怎么做?

这是迄今为止我能做的最多的事情了。

public class PICalculate {

    public static void main(String[] args) {
        System.out.println(calculatePI(5000000) * 4);
    }

    static double calculatePI(int n) {
        double result = 0.0;
        if (n < 0) {
            return 0.0;
        }
        for (int i = 0; i <= n; i++) {
            result += Math.pow(-1, i) / ((2 * i) + 1);
        }
        return result;
    }
}

最佳答案

最直接但不是最佳的方法是在您拥有的线程之间分配序列元素。即,如果您有 4 个线程,线程一将使用 n%4 == 0 个元素,线程 2 将使用 n%4 == 1 个元素,依此类推

public static void main(String ... args) throws InterruptedException {

    int threadCount = 4;
    int N = 100_000;
    PiThread[] threads = new PiThread[threadCount];
    for (int i = 0; i < threadCount; i++) {
        threads[i] = new PiThread(threadCount, i, N);
        threads[i].start();
    }
    for (int i = 0; i < threadCount; i++) {
        threads[i].join();
    }
    double pi = 0;
    for (int i = 0; i < threadCount; i++) {
        pi += threads[i].getSum();
    }
    System.out.print("PI/4 = " + pi);

}

static class PiThread extends Thread {

    private final int threadCount;
    private final int threadRemainder;
    private final int N;
    private double sum  = 0;

    public PiThread(int threadCount, int threadRemainder, int n) {
        this.threadCount = threadCount;
        this.threadRemainder = threadRemainder;
        N = n;
    }


    @Override
    public void run() {
        for (int i = 0; i <= N; i++) {
            if (i % threadCount == threadRemainder) {
                sum += Math.pow(-1, i) / (2 * i + 1);
            }
        }
    }

    public double getSum() {
        return sum;
    }
}

PiThread 更高效,但可以说更难阅读,如果循环更短:

public void run() {
    for (int i = threadRemainder; i <= N; i += threadCount) {
        sum += Math.pow(-1, i) / (2 * i + 1);
    }
}

如果您不想按顺序和时间限制元素的数量,您可以遵循以下方法。但请注意,它仍然受限于 Long.MAX_VALUE,您必须使用 BigIntegers、BigDecimals 或任何其他合理的方法来改进它

public static volatile boolean running = true;

public static void main(String ... args) throws InterruptedException {
    int threadCount = 4;
    long timeoutMs = 5_000;
    final AtomicLong counter = new AtomicLong(0);
    PiThread[] threads = new PiThread[threadCount];
    for (int i = 0; i < threadCount; i++) {
        threads[i] = new PiThread(counter);
        threads[i].start();
    }

    Thread.sleep(timeoutMs);
    running = false;

    for (int i = 0; i < threadCount; i++) {
        threads[i].join();
    }

    double sum = 0;
    for (int i = 0; i < threadCount; i++) {
        sum += threads[i].getSum();
    }
    System.out.print("counter = " + counter.get());
    System.out.print("PI = " + 4*sum);

}

static class PiThread extends Thread {

    private AtomicLong counter;
    private double sum  = 0;

    public PiThread(AtomicLong counter) {
        this.counter = counter;
    }


    @Override
    public void run() {
        long i;
        while (running && isValidCounter(i = counter.getAndAdd(1))) {
            sum += Math.pow(-1, i) / (2 * i + 1);
        }
    }

    private boolean isValidCounter(long value) {
        return value >= 0 && value < Long.MAX_VALUE;
    }

    public double getSum() {
        return sum;
    }
}

关于java - Java中如何使用多线程编写圆周率计算程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41094056/

相关文章:

algorithm - 计算 Pi 的贝拉德算法

java - 使用 while 循环和递归方法计算 Pi (Java)

java - NotificationListenerService.cancelNotification 抛出 NullPointerException

php - 在 PHP 中启动新进程/线程的最简单方法

java - 未调用handleMessage函数

multithreading - 从非主线程绘制到主窗体 Canvas

JavaFX mp3音频、mp4音频、文本数据叠加

c++ - 实现 Bailey-Borwein-Plouffe

java - java中ObjectInputStream中的IOException

java - 查明 MapLoader 何时在 Hazelcast 中完成(急切)加载