Ваш main
метод возвращается , но проблема в том, что ваша JVM не завершает работу.Вы можете проверить это, переименовав свой метод main
во что-то другое, например doMain()
, а затем записав main
как:
public static void main(String[] args) {
doMain();
System.out.printf("here");
}
. Вы увидите, что вы получите результат, ноПрограмма не заканчивается.
В результате Executors.newCachedThreadPool
использует фабрику потоков по умолчанию , которая создает потоки, не являющиеся демонами.Когда ваш метод main
вернется, JVM будет ожидать завершения всех потоков, не являющихся демонами (это то, что отличает их от потоков демонов - JVM их не ждет).Поскольку все ваши Runnables работают вечно, потоки, не являющиеся демонами, никогда не завершатся, а JVM никогда не завершится.
Что вы можете сделать?Некоторые параметры:
- Используйте перегрузку
newCachedThreadPool(ThreadFactory)
, предоставляя ThreadFactory, который создает потоки демонов - Использование
shutdownNow()
на вашемExecutorService.Это отправит прерывание на каждый из запущенных потоков.Вам все равно придется проверять это в каждом потоке, либо вызывая метод, который выдает InterruptedException
, либо явно вызывая Thread.currentThread().isInterrupted()
.
Для подхода shutdownNow
обратите внимание, что прерываниесам по себе поток не достаточно, чтобы остановить его - код, работающий в этом потоке, должен взаимодействовать, проверяя его прерванное состояние (используя один из этих двух подходов) и соответствующим образом завершая работу.Например, вы можете заменить while(true)
на while (!Thread.currentThread().isInterrupted())
.