Где я начинаю исследовать свой процесс Java, который не закончится?

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

Сокращенный stacktrace второго потока:

   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() 
10
задан Andrzej Doyle 13 July 2010 в 11:17
поделиться

5 ответов

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

public void run() {
    while(true) { //"true" or some condition that never gets a chance to be false
        //do thread related work
    }
}
0
ответ дан 4 December 2019 в 04:52
поделиться

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

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

0
ответ дан 4 December 2019 в 04:52
поделиться

Думаю, дампы потоков и отладчики.

0
ответ дан 4 December 2019 в 04:52
поделиться

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

  1. Укажите ThreadFactory , который создает потоки демона ( ThreadFactoryBuilder класс из Guava упростит это.)
  2. Вызов shutdown () на вашем ExecutorService как часть завершения работы приложения (например, в конце вашего метода main .)
1
ответ дан 4 December 2019 в 04:52
поделиться

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

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

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

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

0
ответ дан 4 December 2019 в 04:52
поделиться