使用许多线程时如何避免瓶颈?



我有以下循环:

// myList is an ArrayList (10000 elements)
for(MyObject test : myList) {
test.calculate();
}

我认为它是并行化的良好候选者,因为每个calculate()操作都不依赖于其他任何东西,它只使用同一对象中的一些变量进行一些数学运算。

我知道执行以下操作会对性能产生负面影响,因为我将创建 10000 个线程,这将在我的 4 核处理器上创建一个巨大的队列:

// myList is an ArrayList (10000 elements)
for(MyObject test : myList) {
Thread thread = new Thread() {
public void run() {
test.calculate();
}  
};
thread.start();
}

问题是,在此类方案中使用多个线程以避免排队的建议方法是什么?

一个简单的方法是使用ExecutorService- 根据您的描述,您希望每个处理器使用一个线程:

int nThreads = Runtime.getRuntime().availableProcessors();
ExecutorService executor = Executors.newFixedThreadPool(nThreads);
for (MyObject test: myList) {
executor.submit(test::calculate);
}
executor.shutdown();

执行器维护一个内部队列,该队列将保存任务,直到前一个任务完成。

一种更简单的方法是利用 Java 8 并行流。

myList.parallelStream().forEach( MyObject::calculate);

JVM 为此类任务维护一个线程池,其线程数与计算机上的内核(或超线程(数一样多。它不会在每次遇到并行代码时启动新池;它也不会为每次迭代启动一个新线程。

当然,对于任何性能问题,请进行基准测试。在多个线程之间分叉工作,然后联接结果(大概你想捕获结果(有一些开销。因此,请确保节省的成本超过开销。

最新更新