ExecutorService shutdownNow не завершает работу JVM - PullRequest
0 голосов
/ 23 июня 2019

Я изучаю ExecutorService, представленный в Java 1.5

Кажется, что следующий пример не соответствует ожидаемому поведению:

public static void main(String[] args) throws InterruptedException,
ExecutionException,TimeoutException  {

    Callable<String> task = () -> {
        int counter = 0;
        while(true) {
            //infinite loop will never exit
            if(counter == 7) {
                break;
            }
        }
        return "abc";
    };

    ExecutorService service = Executors.newSingleThreadExecutor();          
    try {
    Future<String> future = service.submit(task);

        System.out.println("result = " + future.get(10000,TimeUnit.MILLISECONDS));
    }finally {
        System.out.println("<<<< finally >>>>");
        service.shutdownNow();
    }



}

Просмотр документации по Java для этого метода:

Пытается остановить все активно выполняющиеся задачи, останавливает обработку ожидающих задач и возвращает список задач, ожидающих выполнения.

Этот метод не ожидает завершения активно выполняемых задач.Используйте awaitTermination, чтобы сделать это.

Нет никаких гарантий, кроме попыток изо всех сил прекратить обработку активно выполняемых задач.Например, типичные реализации будут отменены через Thread.interrupt, поэтому любая задача, которая не отвечает на прерывания, может никогда не завершиться.

Так что в идеале я ожидал, что после указанного времени ожидания я получу Timeoutисключение, а затем ExecutorService принудительно завершит работу, но этого не произойдет.

Посмотрел документ Java - и, похоже, он указывает на то, что нет никаких гарантий, что он выключится.

Если егоне гарантировано, тогда этого следует избегать?

1 Ответ

2 голосов
/ 23 июня 2019

Посмотрел на документацию по Java - и, похоже, он указывает на то, что нет никаких гарантий, что он отключится.

Correct.

Если это не гарантировано, то следует ли этого избегать?

Нет.

На самом деле вам следует использовать ExecutorService таким образом, чтобы избежать или обойти ограничения; например,

  • Реализуйте любые задачи, которые могут быть долгосрочными и которые должны быть убиваемыми, чтобы они правильно обрабатывали прерывания. Если вы сделаете это правильно, то ваш ExecutorService прекратит работу.

  • Не зависит от фактического выключения ExecutorService. Например, вы можете договориться о том, что когда приложение должно завершить работу, оно выполняет следующее:

    1. звонит shutdownNow()
    2. он вызывает awaitTermination(...) с соответствующим временем ожидания
    3. если ExecutorService не завершается, то вызывается System.exit(...) для завершения приложения.
  • Настройте ExecutorService для создания рабочих потоков в качестве потоков демонов; см. Превращение ExecutorService в демон в Java .

    Поток демона не будет препятствовать выходу JVM. Но учтите, что вам нужно быть осторожным. Если все потоки, не являющиеся демонами, завершены, JVM отключит штепсель, не прерывая выполнение каких-либо задач, выполняемых в данный момент ExecutorService.

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