我有一个不会结束的Java应用程序。 main方法完成,但线程保持活动状态,应用程序不会结束。问题是,似乎没有任何监视器锁定/等待,所以我不明白为什么它没有结束。根据Eclipse,我留下了两个非守护进程线程。一个标记为[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()
答案 0 :(得分:1)
您需要执行以下两项操作之一来终止ExecutorService
主题:
ThreadFactory
(来自ThreadFactoryBuilder的Guava
类将使这更容易。)shutdown()
上致电ExecutorService
(例如,在main
方法结束时。)答案 1 :(得分:0)
线程转储和调试器将是我的猜测。
答案 2 :(得分:0)
不确定应用程序的大小,但我会检查您创建的所有线程,并确保在应用程序执行完毕后干净地退出其运行方法。在某个地方,在一个线程中,你可能有以下代码:
public void run() {
while(true) { //"true" or some condition that never gets a chance to be false
//do thread related work
}
}
答案 3 :(得分:0)
Unsafe.park
,尽管名字听起来很恐怖,但通常被各种阻塞调用使用(特别是那些新的(ish)java.util.concurrent
包中)。
如果你在堆栈的下方看几帧,你会看到类似java.util.concurrent.LinkedBlockingQueue.take
(即一些JDK库类)的东西,然后是类似com.example.myapp.MyClass.getNextJob
的东西(即你正在使用该库的类)类)。
如果我不得不冒险猜测,我会说你正在做一些永远阻止的电话 - 所以当没有什么可以再回来的时候,这个线程只是坐在那里等待“下一个”项目。您可以通过设置某种“已完成”标志来解决此问题,然后中断等待线程或使阻塞调用超时,让它检查标志。根据您的代码中的任何一个或替代方案都是可行的,但希望这足以让您入门。
编辑:看到堆栈跟踪,finnw is right,您需要关闭执行服务。
答案 4 :(得分:0)
您的任务被阻止等待队列中的数据。 Take没有与之相关的超时。
在创建任务线程时保持对其的引用。在关闭时,调用线程上的中断方法。您可能还需要修改调用take的工作处理循环,以便在捕获InterruptedException时退出。