2013-07-10 2 views
2

Моя проблема в том, что мое завершение происходит слишком рано, не дожидаясь, пока процесс очистится.Когда процесс Java умирает после остановки?

Однако, если в моем отключенном потоке я добавляю while(true) Thread.sleep(1000);, процесс очищается отлично и, очевидно, никогда не выключается.

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

Так как я могу сказать, что выключение происходит, когда завершается завершающий поток run. Я думаю, что из этих знаний я могу исправить это, закончив его в цикле опроса, опросив для Future, что означает успешное завершение остальных моих процессов. Но это кажется неправильным - я просто хочу дождаться завершения всех потоков, отличных от daemon, и я, конечно, не хочу делать опрос.

  1. Я исправляю, что завершение работы завершено, когда завершается завершение работы run метода завершения работы выключателя?
  2. Что такое хороший способ выполнения выключения, ожидая завершения моих текущих задач завершения?

ответ

1

Am Я исправляю, что завершение работа завершается, когда метод запуска НИТИ Shutdown Гук завершает? Каков наилучший способ выполнения выключения, ожидающий завершения моих текущих задач выключения?

Сделайте выключения нитку, не являющиеся демонами

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

+0

* shutdown thread * выходит чисто; он просто запускает много асинхронной (будущей) работы, которую я также хотел бы подождать. Но наши обещания асинхронны и не блокируются. Похоже, что блокирующее ожидание сделает трюк. – djechlin

+0

Вам нужно сделать асинхронный материал в потоках не-демона или иметь хотя бы один поток без демона, который ждет, пока все будущие/асинхронные вещи не будут завершены. Примечание. Если эти потоки выполнялись до System.exit(), они были бы уничтожены и их нужно будет перезапустить в интересах выключения. Возможно, ваши библиотеки не справятся с этим слишком хорошо. –

+0

Он закрывается, пока у меня все еще есть пулы потоков без демона. – djechlin

2

Как правило, процесс Java может останавливаться после того, как все потоки не-daemon прекратились. Обычно это время, когда виртуальная машина будет вызывать крючки отключения.

Крючки будет называться рано (то есть с некоторыми не-демон потоков до сих пор вокруг), если вы убить процесс или позвоните System.exit()

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

Этого нелегко достичь. Вы можете попробовать получить доступ к корню ThreadGroup (у него нет родителя, используйте Thread.currentThread().getGroup(), а затем двигайтесь вверх по цепочке). Все потоки являются дочерними элементами этой группы (или ее подгруппы).

Таким образом, вы можете перемещаться по этому дереву, пока только остается демон-потоки:

int maxWait = 100; 
while(countNonDaemonThreads() > 0 && --maxWait > 0) { 
    Thread.sleep(100); 
} 

Это должно работать, но я не проверял. Обратите внимание, что вам нужно быть осторожным с кодом в потоке отключения; он не должен блокироваться, и вы должны каким-то образом справляться со всеми ошибками, или VM может быть неспособен закончить надлежащим образом.

EDIT Код в коде java.lang.Shutdown является однопоточным, поэтому, если один из блоков блокировки останова блокируется, вся VM висит.

Теперь вопросы:

  1. ВМ заканчивается, когда halt() вызывается. Это последнее, что делает Terminate.run(), так что да, VM должен действительно заканчивается в конце run(). Я даже не думаю, что run() когда-либо вернется. Там могут быть ошибки и собственный код, который может мешать, но так оно и должно быть.

  2. Хорошей практикой является использование пулов потоков для выполнения вашей работы и дождаться их завершения. Заключительные крючки - это последнее средство. Поскольку вы не можете реально повлиять на порядок, и вы не можете быть уверены, что потоки не-демона могут быть все еще вокруг, они хрупки для «последних отключений выключается».

    Используя пулы потоков, вы можете иметь несколько независимых от них, вы можете четко определить, как закрыть пулы и как дождаться их завершения. И самое главное, вы можете создавать свои потоки таким образом, чтобы вы могли их прервать. Когда вы находитесь в выключенном крюке, и один поток без демона отказывается умереть, что вы собираетесь делать? С пулом потоков вы узнаете тип потока, который может быть внутри, и тем самым риск просто прекратить его.

+0

Почему он не должен блокироваться? Я собирался попытаться использовать блокировку для решения этой проблемы. – djechlin