就每个线程的开销而言,ExecutorService是最轻量级的并行执行方法吗



对于一个在循环中重复执行多个相同计算任务的应用程序,ExecutorService是否是在CPU之间分配任务的最合适的解决方案?

下面是我使用这个答案构建的测试应用程序https://stackoverflow.com/a/28632378/2721750发现对于在Intel Core i5 2.5 GHz的2个物理核心上并行运行的2个任务,每个周期的开销约为0.1毫秒。

有没有其他解决方案可以帮助减少开销?

要求是任务需要接收一个参数,并向主线程返回一个值。它们是对所有权API的调用,我无法更改。

package asyncthreadbenchmark;
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;
import java.util.logging.Level;
import java.util.logging.Logger;
public class AsyncThreadBenchmark {
    public static Double CalcResult(Integer p)
    {
        Long startTime = System.nanoTime();
        double d = 0;
        /* Simulating payload for the given number of milliseconds */
        while ((System.nanoTime() - startTime) / 1000000 < p)
        {
            d = Math.PI * Math.pow(Math.log((double)p), Math.E);
        }
        return d;
    }
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        class CalcTask implements Callable<Double> {
            Integer p;
            CalcTask(Integer parameter) {
                p = parameter;
            }
            @Override
            public Double call() {
                return CalcResult(p);
            }
        }
        /* 
        Using Intel Core i5 2.5 GHz dual core, execuction of 10,000 cycles 
        with 6 ms per task max resulted in 61024-61034 ms total.
        That is 0.1 ms overhead for 2 tasks per cycle.
        If the savings from running 2 tasks in parallel exceed 0.1 ms
        it makes sense to use Executor Service. Otherwise...
        */
        ExecutorService executor = Executors.newFixedThreadPool(3);
        try {
            Integer param1, param2, param3;
            param1 = 5;
            param2 = 6;
//            param3 = 4;
            Future aFuture, bFuture, cFuture;
            Double a, b, c;
            Long startTime = System.nanoTime(), elapsed;
            for (long i = 0; i< 10000; i++)
            {
                aFuture = executor.submit(new CalcTask(param1));
                bFuture = executor.submit(new CalcTask(param2));
//                cFuture = executor.submit(new CalcTask(param3));
                try {
                    a = (Double)aFuture.get();
                    b = (Double)bFuture.get();
//                    c = (Double)cFuture.get();
                } catch (InterruptedException | ExecutionException ex) {
//                    Logger.getLogger(AsyncThreadBenchmark.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            elapsed = (System.nanoTime() - startTime) / 1000000;
            System.out.println("Elapsed " + Long.toString(elapsed) + "ms");
        }
        finally {
            executor.shutdown();
        }
    }
}

这取决于你想做什么。

ExecutorService是执行独立的中等粒度任务的首选工具,这些任务具有自然的任务粒度(例如,为用户请求提供服务)

相反,如果您希望执行细粒度的协作任务,例如那些由可并行化问题的递归分解产生的任务,那么您可能需要ForkJoinPool

Java 8中的并行流使用ForkJoinPool来分解和执行流操作。如果您还不是并行方面的专家,那么最好从并行流开始。

相关内容

  • 没有找到相关文章

最新更新