Я хотел бы глобально заменить общий пул потоков, используемый по умолчанию параллельными потоками Java, то есть, например, для
IntStream.range(0,100).parallel().forEach(i -> {
doWork();
});
Я знаю, что можно использовать выделенный ForkJoinPool, отправив такую инструкцию в выделенный пул потоков (см. Пользовательский пул потоков в параллельном потоке Java 8). Вопрос здесь
- Возможно ли заменить обычный ForkJoinPool на некоторую другую реализацию (скажем,
Executors.newFixedThreadPool(10)
? - Можно ли сделать это с помощью некоторых глобальных настроек, например, некоторого свойства JVM?
Примечание. Причина, по которой мне нравится заменять пул F/J, заключается в том, что она, похоже, имеет ошибку, которая делает ее непригодной для вложенных параллельных циклов.
Вложенные параллельные петли имеют низкую производительность и могут приводить к взаимоблокировкам, см. http://christian-fries.de/blog/files/2014-nested-java-8-parallel-foreach.html
Например: следующий код приводит к тупику:
// Outer loop
IntStream.range(0,24).parallel().forEach(i -> {
// (omitted:) do some heavy work here (consuming majority of time)
// Need to synchronize for a small "subtask" (e.g. updating a result)
synchronized(this) {
// Inner loop (does s.th. completely free of side-effects, i.e. expected to work)
IntStream.range(0,100).parallel().forEach(j -> {
// do work here
});
}
});
(даже без дополнительного кода в "do work here", учитывая, что parallelism установлен в < 12).
Мой вопрос - как заменить FJP. Если вам нравится обсуждать вложенные параллельные циклы, вы можете проверить Вложенная Java 8 параллельная для каждого цикла, выполняющая бедные. Ожидается ли такое поведение?.