我有下面的程序使用线程来计算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条答案
按热度按时间ijnw1ujt1#
关于问题2,volatile意味着jvm不应该缓存它,请看这里,所以它不应该缓存,但这在代码中并不重要,因为
result
是Pi
同学们,所以当你们做两个Pi
类示例,并为每个线程提供一个示例,线程使用的是完全独立的result
变量。另外,因为您启动后立即加入线程,所以您发布的代码相当于什么
<thread a>.join
它是否告诉调用它的线程(在本例中是主线程)停止执行,直到<thread a>
完成执行如果希望两个线程同时访问double值,可以移动
result
由于Pi
把它放进去PiCalculator
然后要同时运行两个线程,请将循环更改为如果你搬家了
result
对于顶级类中的一个成员,并且两个线程都已添加到该类中,则该类将已有求和结果,无需求和线程关于问题1,pi/4是.785398,所以我猜这就是你的算法计算的结果,这个误差是由两倍的松散精度造成的,
编辑:看起来你用的是莱布尼兹公式,它收敛到π/4,但是是无限的,所以你停在1000就解释了这个错误
也
Math.pow(-1,i)
相当于1-(i%2)
,会快很多cvxl0en22#
start=end
应该更好。你的问题是你不计算π,而是π/4,只要把结果乘以4,你就会得到它。
另外,并发地启动线程—不要在循环中调用join,构建一个线程数组并在下面的另一个循环中进行join。