我们编写了一个控制台应用程序(将用作服务),它启动了几个工作线程来处理通过 mina 进来的请求。当在特定网络端口上接收到停止信号时,应用程序会离开主循环。这是停止服务的预期方式。这工作得很好,但是当收到停止信号时,应用程序的进程不会立即终止(最多需要 5 分钟)。我们通过日志消息验证了 main 函数按预期快速离开,并且应用程序创建的所有线程也被终止。但应用程序继续运行。
在离开主函数之前仍在运行的线程是:
Signal Dispatcher (java.lang.Thread)
Finalizer (java.lang.ref.Finalizer$FinalizerThread)
Abandoned connection cleanup thread (com.mysql.jdbc.AbandonedConnectionCleanupThread)
main (java.lang.Thread)
pool-2-thread-1 (java.lang.Thread)
Reference Handler (java.lang.ref.Reference$ReferenceHandler)
我们目前正在使用以下 java 版本:
java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)
操作系统是 ubuntu 14.04 LTS。
我对这种行为一无所知,我希望得到一些关于如何进一步调查该问题的提示。
附加信息
我按照建议制作了一个完整的线程转储。四个线程正在等待:
"pool-2-thread-1" prio=10 tid=0x00007fd7fc51f000 nid=0x16200 waiting on condition [0x00007fd800318000]
java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for <0x00000000cceaf660> (a java.util.concurrent.SynchronousQueue$TransferStack)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:226)
at java.util.concurrent.SynchronousQueue$TransferStack.awaitFulfill(SynchronousQueue.java:460)
at java.util.concurrent.SynchronousQueue$TransferStack.transfer(SynchronousQueue.java:359)
at java.util.concurrent.SynchronousQueue.poll(SynchronousQueue.java:942)
at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1068)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
"Abandoned connection cleanup thread" daemon prio=10 tid=0x00007fd7fc23d800 nid=0x161e2 in Object.wait() [0x00007fd800cbb000]
java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000dc2af720> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
- locked <0x00000000dc2af720> (a java.lang.ref.ReferenceQueue$Lock)
at com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:41)
"Finalizer" daemon prio=10 tid=0x00007fd7fc066000 nid=0x161d6 in Object.wait() [0x00007fd801bd6000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000dc03c060> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135)
- locked <0x00000000dc03c060> (a java.lang.ref.ReferenceQueue$Lock)
at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151)
at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)
"Reference Handler" daemon prio=10 tid=0x00007fd7fc064000 nid=0x161d5 in Object.wait() [0x00007fd801cd7000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
- waiting on <0x00000000dc03c108> (a java.lang.ref.Reference$Lock)
at java.lang.Object.wait(Object.java:503)
at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:133)
- locked <0x00000000dc03c108> (a java.lang.ref.Reference$Lock)
有人可以确认,我应该调查 pool-2-thread-1 吗?我不确定如何解释结果。
解决方案 最后调用acceptor.dispose(MINA)就成功了......