Я читаю Java 8 в действии, глава 11 (около CompletableFuture
с), и это заставило меня задуматься о кодовой базе моей компании.
Книга Java в действии говорит, что если у вас есть кодкак я запишу ниже, вы будете использовать только 4 CompletableFuture
с за раз (если у вас 4-х ядерный компьютер).Это означает, что если вы хотите выполнить, например, 10 операций асинхронно, вы сначала запустите первые 4 CompletableFuture
s, затем вторые 4, а затем 2 оставшиеся, потому что по умолчанию ForkJoinPool.commonPool()
предоставляет только количество потоков.равно Runtime.getRuntime().availableProcessors()
.
В кодовой базе моей компании есть @Service
классы, называемые AsyncHelper
s, которые содержат метод load()
, который использует CompletableFuture
s для загрузки информации о продукте.асинхронно в отдельных кусках.Мне было интересно, используют ли они только 4 потока одновременно.
В базе кода моей компании есть несколько таких асинхронных помощников, например, один для страницы списка продуктов (PLP) и один для страницы сведений о продукте (PDP).).Страница сведений о продукте - это страница, посвященная конкретному продукту, показывающая его подробные характеристики, продукты перекрестных продаж, аналогичные продукты и многое другое.
Было принято архитектурное решение загрузить детали страницы pdp порциями,Предполагается, что загрузка происходит асинхронно, и текущий код использует CompletableFuture
с.Давайте посмотрим на псевдокод:
static PdpDto load(String productId) {
CompletableFuture<Details> photoFuture =
CompletableFuture.supplyAsync(() -> loadPhotoDetails(productId));
CompletableFuture<Details> characteristicsFuture =
CompletableFuture.supplyAsync(() -> loadCharacteristics(productId));
CompletableFuture<Details> variations =
CompletableFuture.supplyAsync(() -> loadVariations(productId));
// ... many more futures
try {
return new PdpDto( // construct Dto that will combine all Details objects into one
photoFuture.get(),
characteristicsFuture.get(),
variations.get(),
// .. many more future.get()s
);
} catch (ExecutionException|InterruptedException e) {
return new PdpDto(); // something went wrong, return an empty DTO
}
}
Как вы можете видеть, в приведенном выше коде нет пользовательских исполнителей.
Означает ли это, что если этот метод загрузки имеет 10 CompletableFuture
s ив настоящее время 2 человека загружают страницу PDP, и у нас есть всего 20 CompletableFuture
с для загрузки, тогда все эти 20 CompletableFuture
с не будут выполняться одновременно, а только 4 одновременно?
Мой коллега сказал мне, что каждый пользователь получит 4 потока, но я думаю, что JavaDoc довольно четко заявляет это:
public static ForkJoinPool commonPool () Возвращает экземпляр общего пула.Этот пул статически построен;на его состояние выполнения не влияют попытки shutdown () или shutdownNow ().Однако этот пул и любая текущая обработка автоматически завершаются по программе System.exit (int).Любая программа, использующая асинхронную обработку задач для завершения до ее завершения, должна вызывать commonPool (). AwaitQuiescence перед выходом.
Это означает, что для всех пользователей нашего веб-сайта имеется только 1 пул с 4 потоками.