我有一个for循环,该循环遍历集合列表。在循环内部,对集合进行了一些选择/更新查询,这些查询不包含其他集合。由于每个集合都有大量数据要处理,因此我想对其进行并行化。
代码段如下所示:
//Some variables that are used within the for loop logic
for(String collection : collections) {
//Select queries on collection
//Update queries on collection
}
如何在Java中实现这一目标?
答案 0 :(得分:2)
您可以使用parallelStream()方法(自Java 8起):
collections.parallelStream().forEach((collection) -> {
//Select queries on collection
//Update queries on collection
});
有关streams的更多信息。
另一种方法是使用执行程序:
try
{
final ExecutorService exec = Executors.newFixedThreadPool(collections.size());
for (final String collection : collections)
{
exec.submit(() -> {
// Select queries on collection
// Update queries on collection
});
}
// We want to wait that the jobs are done.
final boolean terminated = exec.awaitTermination(500, TimeUnit.MILLISECONDS);
if (terminated == false)
{
exec.shutdownNow();
}
} catch (final InterruptedException e)
{
e.printStackTrace();
}
此示例功能更强大,因为您可以轻松知道何时完成工作,强制终止... and more。
答案 1 :(得分:0)
final int numberOfThreads = 32;
final ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
// List to store the 'handles' (Futures) for all tasks:
final List<Future<MyResult>> futures = new ArrayList<>();
// Schedule one (parallel) task per String from "collections":
for(final String str : collections) {
futures.add(executor.submit(() -> { return doSomethingWith(str); }));
}
// Wait until all tasks have completed:
for ( Future<MyResult> f : futures ) {
MyResult aResult = f.get(); // Will block until the result of the task is available.
// Optionally do something with the result...
}
executor.shutdown(); // Release the threads held by the executor.
// At this point all tasks have ended and we can continue as if they were all executed sequentially
根据需要调整numberOfThreads
,以实现最佳吞吐量。更多线程将倾向于更好地利用本地CPU,但可能会导致远程端产生更多开销。为了获得良好的本地CPU利用率,您希望拥有比CPU(/ core)多得多的线程,以便每当一个线程必须等待时,例如对于DB的响应,可以切换另一个线程以在CPU上执行。
答案 2 :(得分:0)
您需要问自己几个问题才能找到正确的答案:
如果我的线程数与CPU内核数一样多,那就足够了吗?
使用parallelStream()
将为您提供与CPU内核一样多的线程。
并行化循环会提高性能还是DB上存在瓶颈?
您可以启动100个线程,以并行方式进行处理,但这并不意味着如果您的数据库或网络无法处理该卷,您的处理速度将提高100倍。数据库锁定在这里也可能是一个问题。
我需要按特定顺序处理数据吗?
如果必须按特定顺序处理数据,这可能会限制您的选择。例如。 forEach()
不保证将按照特定顺序处理集合中的元素,但是forEachOrdered()
可以(以性能成本为准)。
我的数据源是否能够以反应方式获取数据?
在某些情况下,我们的数据源可以以流的形式提供数据。在这种情况下,您始终可以使用RxJava
或WebFlux
之类的技术来处理此流。这将使您能够对问题采取不同的方法。
综上所述,您可以选择所需的方法(执行程序,RxJava等)更适合您的目的。