我有以下程序来计算使用线程的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;
我仍然得到相同的输出,为什么会这样?
答案 0 :(得分:1)
start=end
应该会更好。
你的问题只是你没有计算PI,而是PI / 4,只需将结果乘以4即可得到它。
此外,同时启动你的线程不要在循环中调用join,构建一个线程数组并加入另一个跟随循环。
答案 1 :(得分:0)
关于问题2,volatile意味着jvm不应该将其see here缓存,所以它不会,但这在您的代码中并不重要,因为result
是Pi
类的成员,因此当您创建两个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)
,这会更快