java - 如何让这个计算更快?

时间:2018-01-14 14:40:23

标签: java multithreading concurrency

我的函数是total += Math.sqrt(num) - Math.cbrt(num);我想将它应用于每个数字,直到我确定的最大值(从0开始)。所以我在下面编写了一些代码,使用除法技术来更快地计算。我怎样才能加快这个计算?下面的代码( 8个帖子)需要 20秒才能完成,而非线程需要 150秒才能完成。我相信forkjoinpool我可以让它更快或者parallel streams?如何用它们实现它?

public class Main {

    private static int targetNum = Integer.MAX_VALUE;
    private static int threadCount = 8;
    private static double total = 0;
    public static void main(String[] args) {
    // write your code here
        DecimalFormat df2 = new DecimalFormat(".##");
        long time = System.currentTimeMillis();


        ExecutorService executor = Executors.newFixedThreadPool(threadCount);

        try {
            ArrayList<Future<Double>> futureList = new ArrayList<>();
            for(int a = 0; a < threadCount; a++){
                calculatorService ss = new calculatorService(a*(targetNum/threadCount) ,(a+1) *(targetNum/threadCount));
                futureList.add(executor.submit(ss));
            }
            for(int a = 0; a < threadCount; a++){
                total+= futureList.get(a).get();
            }

            System.out.println("Result= "+ df2.format(total) + "\nTime passed= " + ((System.currentTimeMillis() - time)/1000f));
            executor.shutdown();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
class calculatorService implements Callable<Double>{

    private int start,end;

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

    @Override
    public Double call(){
        double total = 0;
        for (int a = start; a < end; a++) {
            total += Math.sqrt(a) - Math.cbrt(a);
        }
        return total;
    }
}

修改1

futureList.get(a).get();我必须这样做,因为我不知道线程(核心)计数。因此我不能写futureList.get(0).get()+ futureList.get(1).get().....我知道,直到futureList.get(0).get()循环将等待,但他们仍然将会做他们的工作。我的线程数不固定,可以随时改变。

3 个答案:

答案 0 :(得分:3)

当您的应用程序是I / O密集型时,MultiThreading可以从中受益。但是,此应用程序对计算敏感,可能指定threadCount处理器的数量是最佳选择:

private static int threadCount = Runtime.getRuntime().availableProcessors();

答案 1 :(得分:0)

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Main {

    private static int targetNum = Integer.MAX_VALUE;
    private static int threadCount = Runtime.getRuntime().availableProcessors();
    private static double total = 0;
    public static void main(String[] args) {
    // write your code here
        DecimalFormat df2 = new DecimalFormat(".##");
        long time = System.currentTimeMillis();
        List<Future<Double>> futureList = new ArrayList<>();
        int lastSize=futureList.size();

        ExecutorService executor = Executors.newFixedThreadPool(threadCount);

        Runnable sumRunnable= () ->
        {   int sumCalculatedTill=0;
            while(!executor.isTerminated())
            {
                if(lastSize!=futureList.size())
                {
                    for(int i=sumCalculatedTill;i<futureList.size();i++)
                        try {
                            total+=futureList.get(i).get();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (ExecutionException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }

                    sumCalculatedTill=futureList.size();
                }
            }
            System.out.println("Result= "+ df2.format(total) + "\nTime passed= " + ((System.currentTimeMillis() - time)/1000f));
        };
        Thread thread=new Thread(sumRunnable);
        thread.start();

        try {


            for(int a = 0; a < threadCount; a++){
                calculatorService ss = new calculatorService(a*(targetNum/threadCount) ,(a+1) *(targetNum/threadCount));
                futureList.add(executor.submit(ss));

            }
            /*for(int a = 0; a < threadCount; a++){
                total+= futureList.get(a).get();
            }
*/

            executor.shutdown();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
class calculatorService implements Callable<Double>{

    private int start,end;

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

    @Override
    public Double call(){
        double total = 0;
        for (int a = start; a < end; a++) {
            total += Math.sqrt(a) - Math.cbrt(a);
        }
        return total;
    }
}

只是一个想法。让我们讨论更多优化它。

答案 2 :(得分:0)

如何将计算减少到1微秒?容易。

你的总数是:n平方根的总和 - n立方根的总和

数学提示:

double sumOfSquareRoots = 2D * Math.pow((n + 0.5D), 1.5D) / 3D - 0.22474487139;

请参阅https://arxiv.org/pdf/1204.0877.pdf了解立方根:)