С чего начать исследование процесса Java, который не закончится? - PullRequest
9 голосов
/ 13 июля 2010

У меня есть приложение Java, которое не заканчивается.Основной метод завершается, но потоки остаются активными, а приложение не заканчивается.Дело в том, что нет никаких блокировок / ожиданий монитора, поэтому я не могу понять, почему это не заканчивается.Согласно Eclipse, у меня осталось два потока, не связанных с Daemon.Один помечен как [DestroyJavaVM] (выглядит обнадеживающе!), А другой, похоже, заблокирован в Unsafe.park(boolean, long).Как / где я должен начать исследовать это?

Сокращенная трассировка стека второго потока:

   Unsafe.park(boolean, long)
at LockSupport.park(Object)
at AbstractQueuedSynchronizer$ConditionObject.await()
at LinkedBlockingQueue<E>.take()
at ThreadPoolExecutor.getTask()
at ThreadPoolExecutor$Worker.run()
at Thread.run() 

Ответы [ 5 ]

1 голос
/ 13 июля 2010

Для завершения потока ExecutorService необходимо выполнить одно из двух действий:

  1. Укажите <a href="http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/util/concurrent/ThreadFactory.html" rel="nofollow noreferrer">ThreadFactory</a>, который создает потоки демона (класс <a href="http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/util/concurrent/ThreadFactoryBuilder.html" rel="nofollow noreferrer">ThreadFactoryBuilder</a> из Guava * 1008).* сделает это проще.)
  2. Вызовите <a href="http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/util/concurrent/ExecutorService.html#shutdown%28%29" rel="nofollow noreferrer">shutdown()</a> на вашем <a href="http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/api/java/util/concurrent/ExecutorService.html" rel="nofollow noreferrer">ExecutorService</a> как часть завершения работы приложения (например, в конце вашего main метода.)
0 голосов
/ 13 июля 2010

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

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

0 голосов
/ 13 июля 2010

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

public void run() {
    while(true) { //"true" or some condition that never gets a chance to be false
        //do thread related work
    }
}
0 голосов
/ 13 июля 2010

Unsafe.park, несмотря на страшно звучащее имя, обычно используется всеми видами блокирующих вызовов (особенно в новом (ish) java.util.concurrent пакете).

Если вы посмотрите несколько кадровдальше вниз по стеку вы увидите что-то вроде java.util.concurrent.LinkedBlockingQueue.take (т.е. некоторый класс библиотеки JDK), за которым следует что-то вроде com.example.myapp.MyClass.getNextJob (т.е. ваш класс, который использует класс библиотеки).

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

Редактировать: после просмотра трассировки стека, finnw прав , что вам нужноотключите службу исполнителя.

0 голосов
/ 13 июля 2010

Дампы потоков и отладчики были бы моей догадкой.

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