计算线程java中的pi

时间:2017-07-14 17:54:00

标签: java multithreading

我有以下程序来计算使用线程的Pi的值,为简单起见,我保持最多2个线程。

public class PiCalculator {

class Pi implements Runnable{
    int start;
    int end;
    volatile double result;

    public Pi(int start, int end) {
        this.start = start;
        this.end = end;
    }

    @Override
    public void run() {
        for(int i = start; i < end; i++) {
            result += Math.pow(-1, i) / ((2 * i) + 1);
        }
        System.out.println(Thread.currentThread().getName() + " result =" + result);
    }

    public double getResult(){
        return result;
    }
}

public static void main(String[] args) throws InterruptedException {
    int maxThreads = 2;
    int maxValuePerThread = 1000 / maxThreads;
    int start = 0;
    int end = maxValuePerThread;
    double resultOut = 0d;
    PiCalculator pc = new PiCalculator();
    for(int i = 0; i < 2; i++) {
        Pi p = pc.new Pi(start, end);
        Thread t = new Thread(p);
        t.setName("thread" + i);
        t.start();
        t.join();
        start = start + end;
        end = end + maxValuePerThread;
        resultOut += p.getResult();
    }
    System.out.println("Final result = " + resultOut);
}

}

1)为什么我得到低于结果?我做错了什么?

thread0 result =0.7848981638974463
thread1 result =2.4999956250242256E-4
Final result = 0.7851481634599486

Pi值为3.14 .....对吧?

2)当我改变

volatile double result;

double result;

我仍然得到相同的输出,为什么会这样?

2 个答案:

答案 0 :(得分:1)

start=end应该会更好。

你的问题只是你没有计算PI,而是PI / 4,只需将结果乘以4即可得到它。

此外,同时启动你的线程不要在循环中调用join,构建一个线程数组并加入另一个跟随循环。

答案 1 :(得分:0)

关于问题2,volatile意味着jvm不应该将其see here缓存,所以它不会,但这在您的代码中并不重要,因为resultPi类的成员,因此当您创建两个Pi类实例并为每个线程提供一个时,线程使用完全独立的result个变量。另外,因为你开始然后立即加入线程,你发布的代码相当于

int maxThreads = 2;
int maxValuePerThread = 1000 / maxThreads;
int start = 0;
int end = maxValuePerThread;
double resultOut = 0d;
PiCalculator pc = new PiCalculator();
for(int i = 0; i < 2; i++) {
    Pi p = pc.new Pi(start, end);
    p.run();
    start = start + end;
    end = end + maxValuePerThread;
    resultOut += p.getResult();
}

<thread a>.join的作用是告诉调用它的线程(在本例中是主线程)在<thread a>完成执行之前停止执行

如果您想要让两个线程同时访问您的double值,则可以将result移出Pi并将其放入PiCalculator

然后同时运行两个线程,将循环更改为

int maxThreads = 2;
int maxValuePerThread = 1000 / maxThreads;
int start = 0;
int end = maxValuePerThread;
PiCalculator pc = new PiCalculator();
Thread[] threads=new Thread[2];
for(int i=0; i<2;i++){
    threads[i]=new Thread(pc.new Pi(start,end));
    threads[i].start();
    start = start + end;
    end = end + maxValuePerThread;
}

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

如果你将result移动到顶级类的成员,并且两个线程都已添加到它,它将已经有了总结结果,不需要对线程求和

关于问题1,pi / 4是.785398, 所以我猜测你的算法计算的是什么,错误是由于精度上升了一倍,

编辑:看起来您正在使用leibniz formula收敛到pi / 4但是无限,所以您在1000处停止的事实解释了错误

同样Math.pow(-1,i)相当于1-(i%2),这会更快