Не все запросы отправляются, потому что ( предупреждение спойлера! ) JVM просто завершается.
Как вы, возможно, знаете, условия для завершения JVM :1007 *
происходит одно из следующих действий:
- Был вызван метод
exit
класса Runtime
, и диспетчер безопасности разрешил выполнение операции выхода. - Все потоки, которые не являются потоками демона, умерли, либо возвращаясь из вызова метода run, либо выбрасывая исключение, которое распространяется за пределы метода run.
Очевидно, что это не первый случай, поэтому он должен быть вторым.
Первое, на что нужно обратить внимание, это то, что вы позволили своему методу main()
выйти:
- вы звоните
CompletableFuture.allOf()
, но вы ничего не делаете с результатом, поэтому он не блокируется (без join()
вызова); - вызов
ExecutorService.shutDown()
только сообщаетвыполнить до завершения, он не ждет его.
Первоначально основной поток является единственным потоком, не являющимся демоном, поэтому этого должно быть достаточно для выхода из JVM.Но в этом и заключается разница между двумя исполнителями:
newFixedThreadPool()
реализован с помощью ThreadPoolExecutor
, который использует Executors.defaultThreadFactory()
, который создает потоки, не являющиеся демонами; newWorkStealingPool()
реализован с помощью ForkJoinPool
, который вызывает setDaemon(true)
во всех потоках, которые он создает¹.
К сожалению, это не документировано, но в основном это сводится кна Почему следующее приложение немедленно завершает работу при использовании ForkJoinPool, а не когда я использую ThreadPoolExecutor?
Итак, два возможных решения вашей проблемы:
- вызов
join()
после allOf()
- вызов
awaitTermination()
на исполнителя после shutdown()
¹ Как отметил teppic в комментариях ,это не было документировано в Java 8, но это теперь с Java 9 .