.parallelStream()
不保证多线程,因为它只会创建等于您拥有的内核数的线程。要真正强制多个线程同时执行此操作,您需要将 .parallelStream() 与 .parallelStream() 一起使用ForkJoinPool
。
使用 ForkJoinPool 实现高性能
List<Employee> employees = new ArrayList();
ForkJoinPool forkJoinPool = new ForkJoinPool(50);
try {
forkJoinPool.submit(() -> employeeIds.parallelStream().forEach(empId -> {
Employee em = employeeService.fetchEmployeedetails(empId);
synchronized(employees) {
employees.add(em);
}
})).get();
} catch (Exception e) {
e.printStackTrace();
throw new BusinessRuleException(ErrorCodeEnum.E002501.value(), e.getMessage());
} finally {
if (forkJoinPool != null) {
forkJoinPool.shutdown(); // always remember to shutdown the pool
}
}
这将确保 parallelStream()创建最多 50 个线程,而不是取决于系统的内核数。确保你不要忘记shutdown()
在 finally 块中的池。并且不要忘记.get();
哪个触发了线程的执行。
ArrayList 对修改不是线程安全的,但synchronized()
会提供这种安全性。由于添加到列表是非常小的操作,因此它也不会长时间保持线程。
通过这种方法,您将看到巨大的性能改进。
如何为线程选择最佳数量
线程过多会导致上下文切换并减慢进程。线程太少会使系统未得到充分利用。最佳线程数通常是您拥有的内核数的 10 倍左右。还取决于您将在线程中花费的时间。我通常传递一个环境变量,以便我可以在需要时调整数字 50。但是在我们拥有的四核实例上进行了相当多的实验后,我已经达到了 50。
@Value("#{systemEnvironment['parallelism'] ?: 50}")
protected int parallelism;
然后使用ForkJoinPool forkJoinPool = new ForkJoinPool(getParallelism());