如何用Java编写多线程PI计算程序?

如何用Java编写多线程PI计算程序?,java,multithreading,pi,approximation,Java,Multithreading,Pi,Approximation,我需要创建一个程序,使用Java多线程计算常数PI的近似值 我打算用Gregory Leibniz级数来计算PI/4的结果,然后乘以4得到PI近似值 但我对这个项目有些担心: 如何分离计算过程,以便为程序实现多线程处理?因为公式是求和的,我不知道如何把它们分成几部分,最后我会把它们全部收集起来 我在考虑这样一个事实,即程序将无限执行公式,因此用户需要提供一些配置执行的方法,以确定何时停止并返回结果。有可能吗?我该怎么做 到目前为止,这是我能做的最多的了 public class PICalcu

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

我打算用Gregory Leibniz级数来计算PI/4的结果,然后乘以4得到PI近似值

但我对这个项目有些担心:

  • 如何分离计算过程,以便为程序实现多线程处理?因为公式是求和的,我不知道如何把它们分成几部分,最后我会把它们全部收集起来
  • 我在考虑这样一个事实,即程序将无限执行公式,因此用户需要提供一些配置执行的方法,以确定何时停止并返回结果。有可能吗?我该怎么做
  • 到目前为止,这是我能做的最多的了

    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;
        }
    }
    
    公共类PICalculate{
    公共静态void main(字符串[]args){
    系统输出打印项次(calculatePI(5000000)*4);
    }
    静态双计算EPI(整数n){
    双结果=0.0;
    if(n<0){
    返回0.0;
    }
    
    对于(int i=0;i来说,最直接但不是最理想的方法是在线程之间分配序列元素。例如,如果有4个线程,线程1将使用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;
        }
    }
    
    publicstaticvoidmain(String…args)抛出InterruptedException{
    int threadCount=4;
    int N=100_000;
    PiThread[]threads=新的PiThread[threadCount];
    对于(int i=0;i对于(int i=0;i)该数列收敛得非常慢……我想你对线程理解得不太好,所以回去阅读教科书并练习一些示例。多线程方法的一个问题是,为了获得好的结果,需要首先添加小项,这是由于浮点舍入。还要注意,该数列非常慢收敛。@Bathsheba“先加小项”是什么意思?这是浮点运算的一个怪癖。将一个非常小的数字加到一个非常大的数字上,计算结果将简单地变成一个更大的数字。因此,在对一系列的项求和时,你需要小心:你需要先从小项开始。Long.MAX_值的限制是什么?还有,如何计算第二种方法有效吗?每个线程将等待另一个线程死亡的时间,然后继续执行?我仍然不知道每个线程如何保持自己的结果,而另一个线程如何不执行之前的计算?我注意到,在第二种方法中,程序在完成计算后不会退出。Long.MAX_值限制了该数字序列中的元素。所有线程同时运行,在相应的变量中保留部分和。在互补线程执行完成或超时中断后,所有部分和将相加。如果您是对的,则以不同的方式中断线程是正确的,因为join不会杀死它们。您可以将isInterrupted check添加到while循环中,并在连接后中断它们。不需要新线程。键盘截取在主线程中完成。例如,您可以使用
    thread.sleep(5_000)
    替换
    Scanner-Keyboard=new Scanner(System.in);System.out.println(“按Enter停止计算”);Keyboard.next();
    public void run() {
        for (int i = threadRemainder; i <= N; i += threadCount) {
            sum += Math.pow(-1, i) / (2 * i + 1);
        }
    }
    
    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;
        }
    }