Изящное отключение потоков и исполнителя

Вы можете построить XmlSlurper без осознания пространства имен в пространстве имен так:

import groovy.xml.XmlUtil

def pom = new XmlSlurper( false, false ).parse( 'pom.xml' )
println XmlUtil.serialize(pom)

Который должен дать вам ответ, который вы хотите ... В настоящее время нет идеи о том, как для сохранения комментариев во время цикла slurp / serialize: - (

Как вы говорите, это может быть возможно с XmlParser, но мои текущие попытки потерпели неудачу :-( Здесь некоторый код который может приблизить вас, но пока я не имел успеха: - (

34
задан skaffman 26 July 2010 в 07:34
поделиться

3 ответа

Типичное упорядоченное завершение работы ExecutorService может выглядеть примерно так:

final ExecutorService executor;

Runtime.getRuntime().addShutdownHook(new Thread() {
    public void run() {
        executor.shutdown();
        if (!executor.awaitTermination(SHUTDOWN_TIME)) { //optional *
            Logger.log("Executor did not terminate in the specified time."); //optional *
            List<Runnable> droppedTasks = executor.shutdownNow(); //optional **
            Logger.log("Executor was abruptly shut down. " + droppedTasks.size() + " tasks will not be executed."); //optional **
        }
    }
});

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

Обратите внимание, что приведенное выше решение будет работать, когда пользователь выдает прерывание вашему процессу java или когда ваша ExecutorService содержит только потоки демона. Если вместо этого ExecutorService содержит потоки, не являющиеся демонами, которые не завершились, JVM не будет пытаться завершить работу, и, следовательно, обработчики завершения не будут вызываться.

Если вы пытаетесь завершить процесс как часть дискретного жизненного цикла приложения (не службы), то код завершения не следует помещать в ловушку отключения, а в соответствующее место, где программа предназначена для завершения.

61
ответ дан 27 November 2019 в 16:28
поделиться

В книге "Java Concurrency in Practice" говорится:

7.4. Завершение работы JVM

JVM может завершаться как в упорядоченным или внезапным образом. Упорядоченное выключение инициируется, когда последний "нормальный" (недемонский) поток завершается, кто-то вызывает System.exit, или другими специфическими для платформы средствами (например, посылкой SIGINT или нажатием клавиши Ctrl-C). [...]

7.4.1. Крючки выключения

При упорядоченном выключении JVM сначала запускает все зарегистрированные крючки выключения. Крючки выключения - это незапущенные потоки. которые регистрируются с помощью Runtime.addShutdownHook. JVM не дает никаких гарантий относительно порядка, в котором запускаются крючки выключения. Если какой-либо потоки приложения (демон или недемон) все еще запущены во во время выключения, они продолжают выполняться одновременно с выключением процессом. Когда все крючки выключения завершены, JVM может выбрать запуск финализаторы, если runFinalizersOnExit имеет значение true, а затем останавливается. JVM не предпринимает никаких попыток остановить или прервать любые потоки приложения, которые все еще выполняются во время завершения работы; они резко завершаются, когда JVM в конечном итоге останавливается. Если выключение крючки или финализаторы не завершаются, то упорядоченный процесс выключения "зависает", и JVM должна быть выключена резко. [...]

Важными битами являются, "JVM не пытается остановить или прервать любые потоки приложения, которые все еще выполняются во время выключения; они резко завершаются, когда JVM в конечном итоге останавливается." Так что я полагаю, что соединение с БД резко прервется, если нет крючков выключения для изящной очистки (если вы используете фреймворки, они обычно предоставляют такие крючки выключения). По моему опыту, сессия с БД может оставаться до тех пор, пока она не завершится по таймеру БД, и т.д., когда приложение завершается без таких крючков.

7
ответ дан 27 November 2019 в 16:28
поделиться

Вы можете либо вызвать shutdown() на ExecutorService:

Инициирует упорядоченное завершение работы, в котором ранее представленные задачи выполняются, но новые задания не принимаются приниматься.

или вы можете вызвать shutdownNow():

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

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

Какой из них вы вызовете, зависит от того, насколько сильно вы хотите, чтобы он прекратился....

3
ответ дан 27 November 2019 в 16:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: