为什么在java中多线程缓慢循环?

时间:2015-05-15 19:12:04

标签: java multithreading

我有以下2个用于计算Pi的代码:

代码1:

public class LeibnizFormula implements Callable<Double> {

    private double pi;
    private double i;
    private double from;
    private double to;
    private double denominator;

    public double getI() {
        return i;
    }

    public void setI(double i) {
        this.i = i;
    }

    public double getFrom() {
        return from;
    }

    public void setFrom(double from) {
        this.from = from;
    }

    public double getTo() {
        return to;
    }

    public void setTo(double to) {
        this.to = to;
    }

    public double getPi() {
        return pi;
    }

    public void setPi(double pi) {
        this.pi = pi;
    }

    public double getDenominator() {
        return denominator;
    }

    public void setDenominator(double denominator) {
        this.denominator = denominator;
    }

    public LeibnizFormula(double from, double to, double denominator) {
        super();
        this.from = from;
        this.to = to;
        this.denominator = denominator;
    }

    @Override
    public Double call() throws Exception {
        // TODO Auto-generated method stub
        for(i = from; i <= to; i++){
            if (i % 2 == 0) {
                pi = pi + (1 / denominator);
            } else {
                pi = pi - (1 / denominator);
            }

            denominator += 2;
        }
        return pi;
    }

}

public static void main(String[] args) throws InterruptedException, ExecutionException {
    System.out.println("Main 1");
    long start = System.nanoTime();
    double pi = 1d;
    double limit = 20000000; 
    double n = 1000000000d;
    double from =0;
    double to=0;
    double a = 0d;
    double denominator = 0;
    a = Math.round(n/limit);

    if (a == 0d) {
        a = 1;
    }

    for (double i=0d; i< a; i++) {
        if (i + 1d == a) {
            from = to + 1;
            to = (int)n;
        } else {
            to = to + limit;
            from = to - limit + 1d;
        }

        denominator = 2 * from + 1;
        LeibnizFormula leibniz = new LeibnizFormula(from, to, denominator);
        FutureTask f = new FutureTask(leibniz);
        Thread t = new Thread(f, "" + i);
        t.start();
        t.join();
        pi += (Double) f.get();
    }

    long time = System.nanoTime() - start;
    System.out.println("took " + time / 1000000 / 1e3);
    System.out.println(pi * 4d);        
}

耗时35.255秒,结果:3.1415926545880506

代码2:

n = 10000
k = 10
mat = matrix(runif(n * k), nrow = n)

花了36.062,结果:3.141592654589748

我想问:

1.当我在循环中创建并启动线程时,它仍会创建许多线程并且并行处理并且不是吗?

2.Sum以大双数返回的值是否准确。这样做是否会导致操作错误,从而导致错误的数字很大?

1 个答案:

答案 0 :(得分:2)

嗯,原因不止一个。

首先,重要的是要理解,线程本身具有显着的开销,因此即使设计良好的算法也可能表现得比直接期望它们更差(如果没有足够的负载或负载,则会比连续的替代方案更差)平衡是不对的。

其次,虽然你使用线程,但你在循环中开始你的线程,并在启动后立即加入它们。这样你就不会进行任何真正的并行计算,因此你不能指望任何性能增益:(