java线程中的多线程计算pi

jtw3ybtb  于 2021-07-09  发布在  Java
关注(0)|答案(2)|浏览(555)

我有下面的程序使用线程来计算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;

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

ijnw1ujt

ijnw1ujt1#

关于问题2,volatile意味着jvm不应该缓存它,请看这里,所以它不应该缓存,但这在代码中并不重要,因为 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,所以我猜这就是你的算法计算的结果,这个误差是由两倍的松散精度造成的,
编辑:看起来你用的是莱布尼兹公式,它收敛到π/4,但是是无限的,所以你停在1000就解释了这个错误
Math.pow(-1,i) 相当于 1-(i%2) ,会快很多

cvxl0en2

cvxl0en22#

start=end 应该更好。
你的问题是你不计算π,而是π/4,只要把结果乘以4,你就会得到它。
另外,并发地启动线程—不要在循环中调用join,构建一个线程数组并在下面的另一个循环中进行join。

相关问题