Как создать фоновый поток в Java, который позволяет основному приложению полностью завершиться? Это работает в Linux, но не в Windows - PullRequest
4 голосов
/ 15 апреля 2010

У меня есть Java-приложение, которое создает новый поток для выполнения некоторой работы. Я могу запустить новую тему без проблем.

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

Но проблема в том, что когда я запускаю основное приложение из Eclipse или из Ant под Windows, управление не возвращается, если не завершен фоновый процесс.

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

Как запустить поток в фоновом режиме, чтобы элемент управления возвращался в ant после завершения «основного» приложения? (Кстати, когда я запускаю одно и то же приложение под Linux, я могу сделать это без проблем).

Ответы [ 6 ]

4 голосов
/ 15 апреля 2010

Ваш лучший выбор - запустить для этого совершенно независимую программу, которая не зависит от запускаемой программы. Вы можете сделать это с помощью Runtime#exec(), ProcessBuilder или Desktop#open().

2 голосов
/ 15 апреля 2010

Возможно, вы хотите создать поток демона : thread.setDaemon (true).

1 голос
/ 15 апреля 2010

Если я правильно понял вопрос, похоже, что программа работает правильно ... поток main завершает работу и завершается, а поток "background" продолжает работать. JVM не будет завершена, пока не прекратятся все потоки, не являющиеся демонами. Если вы хотите, чтобы процесс JVM завершался при завершении потока main, вам нужно сделать, как указывает Роман, и вызвать Thread.setDaemon(boolean).

Однако, если проблема в том, что поток main завершается правильно, но background никогда не завершается, даже если он завершил задачу, которую вы ему дали, тогда, возможно, background заблокирован.

Лучшим IMO для первого шага является запуск VisualVM в процессе для создания дампа стека и использования его инструментов отладки потоков, чтобы выяснить, что делает background и почему он зависает. (Вы также можете заставить JVM выгружать стек, отправив его kill -QUIT <pid>, если на * nix ... что-то похожее в Windows с ключом Break , но я не могу вспомнить подробности.) дампы стека в Java 6 довольно сложны и будут указывать на возможные взаимоблокировки с объектами, на которых заблокирован каждый поток.

VisualVM просто интересно, так что попробуйте, если вы никогда не использовали его.

0 голосов
/ 17 апреля 2010

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

Вы можете проверить это в eclipse: создайте программу и запустите приложение (например, Notepad.exe). Вы обнаружите, что Java-программа завершается, но красная кнопка все еще активна. Управление не возвращается к затмению, пока вы не закроете свое приложение (например, notepad.exe). Это очевидно потому, что ваша java-программа и execed-программа используют одно и то же командное окно. То же самое происходит в ANT.

В Linux процессы не наследуют командное окно, как в Windows, поэтому управление возвращается к затмению, когда ваш процесс завершается.

В обоих случаях порожденный процесс остается активным, пока не будет завершен.

0 голосов
/ 15 апреля 2010

Управление не вернется из JVM, пока все не будет завершено. Это означает, что все потоки должны возвращаться и все окна должны быть уничтожены () ed - и main должен выйти.

Или вы вызываете System.exit ().

Если это сработало в Linux, я уверен, что вы обнаружите, что ваш фоновый поток также прерван - в противном случае это очень плохо.

0 голосов
/ 15 апреля 2010

Похоже, вам нужен "основной" поток и "фоновый" поток, чтобы быть отдельными процессами.Форк первый процесс, который запускает «основной» поток.Этот процесс, в свою очередь, разветвляет второй процесс, который запускает «фоновый» поток.В Windows вам, возможно, придется запустить фоновый процесс (через Java Runtime.exec() API), используя start /b

Я не понимаю, как это работает в Linux.Process, созданный Runtime.exec(), работает или нет.Когда Java-программа ожидает завершения Process, ей все равно, работает ли один или несколько потоков в подпроцессе.Если вы сможете более четко описать, как он работает в Linux, это может помочь.

...