使用多线程在 Java 中并行化 for 循环
Parallellize a for loop in Java using multi-threading
我是 java 的新手,我想使用执行程序服务或使用 java 中的任何其他方法并行化嵌套 for 循环。我想创建一些固定数量的线程,以便 CPU 不会完全被线程获取。
for(SellerNames sellerNames : sellerDataList) {
for(String selleName : sellerNames) {
//getSellerAddress(sellerName)
//parallize this task
}
}
sellerDataList 的大小 = 1000,sellerNames 的大小 = 5000。
现在我想创建 10 个线程并将相同的任务分配给每个线程。这是针对第 i 个 sellerDataList,第一个线程应该获取 500 个名称的地址,第二个线程应该获取下一个 500 个名称的地址,依此类推。
完成这项工作的最佳方式是什么?
有两种方法可以使其运行并行:Streams和Executors。
使用流
你可以使用并行流,剩下的交给jvm。在这种情况下,您对何时发生的事情没有太多控制权。另一方面,您的代码将易于阅读和维护:
sellerDataList.stream().forEach(sellerNames -> {
Stream<String> stream = StreamSupport.stream(sellerNames.spliterator(), true); // true means use parallel stream
stream.forEach(sellerName -> {
getSellerAddress(sellerName);
});
});
使用 ExecutorService
假设您需要 5 个线程,并且希望能够等到任务完成。然后你可以使用一个有 5 个线程的固定线程池并使用 Future
-s 这样你就可以等到它们完成。
final ExecutorService executor = Executors.newFixedThreadPool(5); // it's just an arbitrary number
final List<Future<?>> futures = new ArrayList<>();
for (SellerNames sellerNames : sellerDataList) {
for (final String sellerName : sellerNames) {
Future<?> future = executor.submit(() -> {
getSellerAddress(sellerName);
});
futures.add(future);
}
}
try {
for (Future<?> future : futures) {
future.get(); // do anything you need, e.g. isDone(), ...
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
如果您使用的是并行流,您仍然可以通过创建自己的 ForkJoinPool 来控制线程。
List<Long> aList = LongStream.rangeClosed(firstNum, lastNum).boxed()
.collect(Collectors.toList());
ForkJoinPool customThreadPool = new ForkJoinPool(4);
long actualTotal = customThreadPool.submit(
() -> aList.parallelStream().reduce(0L, Long::sum)).get();
在这个网站上,描述得很好。
https://www.baeldung.com/java-8-parallel-streams-custom-threadpool
我是 java 的新手,我想使用执行程序服务或使用 java 中的任何其他方法并行化嵌套 for 循环。我想创建一些固定数量的线程,以便 CPU 不会完全被线程获取。
for(SellerNames sellerNames : sellerDataList) {
for(String selleName : sellerNames) {
//getSellerAddress(sellerName)
//parallize this task
}
}
sellerDataList 的大小 = 1000,sellerNames 的大小 = 5000。
现在我想创建 10 个线程并将相同的任务分配给每个线程。这是针对第 i 个 sellerDataList,第一个线程应该获取 500 个名称的地址,第二个线程应该获取下一个 500 个名称的地址,依此类推。
完成这项工作的最佳方式是什么?
有两种方法可以使其运行并行:Streams和Executors。
使用流
你可以使用并行流,剩下的交给jvm。在这种情况下,您对何时发生的事情没有太多控制权。另一方面,您的代码将易于阅读和维护:
sellerDataList.stream().forEach(sellerNames -> {
Stream<String> stream = StreamSupport.stream(sellerNames.spliterator(), true); // true means use parallel stream
stream.forEach(sellerName -> {
getSellerAddress(sellerName);
});
});
使用 ExecutorService
假设您需要 5 个线程,并且希望能够等到任务完成。然后你可以使用一个有 5 个线程的固定线程池并使用 Future
-s 这样你就可以等到它们完成。
final ExecutorService executor = Executors.newFixedThreadPool(5); // it's just an arbitrary number
final List<Future<?>> futures = new ArrayList<>();
for (SellerNames sellerNames : sellerDataList) {
for (final String sellerName : sellerNames) {
Future<?> future = executor.submit(() -> {
getSellerAddress(sellerName);
});
futures.add(future);
}
}
try {
for (Future<?> future : futures) {
future.get(); // do anything you need, e.g. isDone(), ...
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
如果您使用的是并行流,您仍然可以通过创建自己的 ForkJoinPool 来控制线程。
List<Long> aList = LongStream.rangeClosed(firstNum, lastNum).boxed()
.collect(Collectors.toList());
ForkJoinPool customThreadPool = new ForkJoinPool(4);
long actualTotal = customThreadPool.submit(
() -> aList.parallelStream().reduce(0L, Long::sum)).get();
在这个网站上,描述得很好。 https://www.baeldung.com/java-8-parallel-streams-custom-threadpool