Возврат из метода Java до того, как все потоки будут сделаны - PullRequest
0 голосов
/ 29 октября 2018

Можно ли вернуться из метода Java, который запустил потоки до того, как все потоки будут завершены?

Вот мой код:

import java.util.concurrent.*;

public class ExecutorSample {
    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            service.execute(() -> {
                while (true) {
                }
            });
        }
        return;
    }
}

По какой-то причине это не возвращает, чтоЯ не понимаюПочему на возврат основного потока влияют зависания рабочих потоков?

1 Ответ

0 голосов
/ 29 октября 2018

Ваш 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()).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...