Java: how to recover a hanging thread?

Note: I mark this with JClouds, because if you read the whole question and comments that arise, I believe that this is either a bug with JClouds or a misuse of this library.

I have an executable JAR that works, works for a while, shuts down without throwing any errors / exceptions, and then hangs forever when it should exit. I profiled it using VisualVM (paying attention to the current threads), and I also threw it into the print journal operator at the point (at the end of the method main()) where the application freezes. Here is the last part of my main method:

Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
for(Thread t : threadSet) {
    String daemon = (t.isDaemon()? "Yes" : "No");
    System.out.println("The ${t.getName()} thread is currently running; is it a daemon? ${daemon}.");
}

When my JAR executes this code, I see the following output:

The com.google.inject.internal.util.Finalizer thread is currently running; is it a daemon? Yes.
The Signal Dispatcher thread is currently running; is it a daemon? Yes.
The RMI Scheduler(0) thread is currently running; is it a daemon? Yes.
The Attach Listener thread is currently running; is it a daemon? Yes.
The user thread 3 thread is currently running; is it a daemon? No.
The Finalizer thread is currently running; is it a daemon? Yes.
The RMI TCP Accept-0 thread is currently running; is it a daemon? Yes.
The main thread is currently running; is it a daemon? No.
The RMI TCP Connection(1)-10.10.99.8 thread is currently running; is it a daemon? Yes.
The Reference Handler thread is currently running; is it a daemon? Yes.
The JMX server connection timeout 24 thread is currently running; is it a daemon? Yes.

, ( , ), -:

The user thread 3 thread is currently running; is it a daemon? No.
The main thread is currently running; is it a daemon? No.

, , - . , user thread 3 . VisualVM?

enter image description here

, ( , ). Hmmm user thread 3 !

, . - user thread 3:

"user thread 3" prio=6 tid=0x000000000dfd4000 nid=0x2360 waiting on condition [0x00000000114ff000]
    java.lang.Thread.State: WAITING (parking)
        at sun.misc.Unsafe.park(Native Method)
        - parking to wait for  <0x0000000782cba410> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
        at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
        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:744)

    Locked ownable synchronizers:
        - None

, (, , !).

VisualVM / , , user thread 3, :

enter image description here

, , user thread 3 . :

  • , user thread 3, (, , OSS- ), ?
  • , ?

:

, , user thread 3:

ExecutorService myExecutor = Executors.newCachedThreadPool();
for(Node node : nodes) {
    BootstrapAndKickTask bootAndKickTask = new BootstrapAndKickTask(node, ctx);
    myExecutor.execute(bootAndKickTask);
}

myExecutor.shutdown();
if(!myExecutor.awaitTermination(15, TimeUnit.MINUTES)) {
    TimeoutException toExc = new TimeoutException("Hung after the 15 minute timeout was reached.");
    log.error(toExc);

    throw toExc;
}

GitHub Gist, .

+4
3

, , . Apache jclouds , .

, close() api, jclouds ContextBuilder.

+3

, , , , , shutdown()/shutdownNow() ExecutorService. , , , ThreadPoolExecutor, . - , ExecutorService , . , ExecutorService, -, .

, , ThreadPoolExecutor, , .

:

, . , shutdown(), , , , core threads / allowCoreThreadTimeOut (boolean).

, ThreadPoolExecutor, , . docs .

+5

:

  • ( )
  • , , .

. ( , finally)

ExecutorService myExecutor = Executors.newCachedThreadPool();
try {
    for(Node node : nodes) {
        BootstrapAndKickTask bootAndKickTask = new BootstrapAndKickTask(node, ctx);
        myExecutor.execute(bootAndKickTask);
    }
} finally {    
    myExecutor.shutdown();
    if(!myExecutor.awaitTermination(15, TimeUnit.MINUTES)) {
        TimeoutException toExc = new TimeoutException("Hung after the 15 minute timeout was reached.");
        log.error(toExc);
        throw toExc;
    }
}
+1
source

All Articles