如何使用多线程在Java中编写PI计算程序? [英] How to write PI calculation program in Java using multi-thread?

查看:153
本文介绍了如何使用多线程在Java中编写PI计算程序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I need to create a program that can calculate approximation to the constant PI, using Java multi-thread.

我打算使用Gregory-Leibniz系列来计算PI / 4的结果,然后乘以4得到PI近似值。

I'm intent to use Gregory-Leibniz Series to calculate the result for PI / 4, and then multiply by 4 to get the PI approximation.

但我对该计划有一些担忧:

But I have some concern about the program:


  1. 我如何分离计算过程以便我可以为程序实现多线程处理?因为公式是总和,我不知道如何将它们分成几部分然后最后我将收集它们。

  2. 我在考虑这样一个事实:程序将执行无限公式,因此用户需要提供一些配置执行的方法,以确定何时应该停止并返回结果。是否有可能,我该怎么做?

到目前为止,这是迄今为止我能做的最多。

This is so far the most I can do by now.

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个线程,线程1将使用n%4 == 0个元素,thread2与n%4 == 1个元素等等

The most straightforward, but not the most optimal, approach is to distribute the sequence elements between threads you have. Ie, if you have 4 threads, thread one will work with n%4 == 0 elements, thread2 with n%4 == 1 elements and so on

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效率更高,但可能更难阅读,如果循环较短:

PiThread is more efficient, but arguably harder to read, if the loop is shorter:

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

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

In case you don't want to limit yourself with number of elements in sequence and just by time, you may follow an approach below. But note, that it is still limited with Long.MAX_VALUE and you'll have to use BigIntegers, BigDecimals or any other reasonable approach to improve it

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中编写PI计算程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆