开发者

Java thread still in memory after being shutdown

Could some help me fix this. The code below is what I am using to start/stop some Polling service. The Polling service operates with a while(boolean running) loop. Calling Polling.setRunning(false) would terminate the loop.

private static ExecutorService pool = Executors.newSingleThreadExecutor(new ThreadFactory() {
   @Override
   public Thread newThread(Runnable runnable) {
      Thread thread = Executors.defaultThreadFactory().newThread(runnable);
      thread.setDaemon(true);
      return thread;
   }
});

public static void start(){

    pool.submit(new Runnable() {
        public void run(){
            try{
                System.out.println("Starting Polling...");
                Polling.start();
            } catch(Exception e){
                e.printStackTrace();
            }
        }
    });

}

public static void stop(){

    System.out.println("Stopping Polling...");
    Polling.setRunning(false);
    pool.shutDownNow();
}

public static void main(String[] args) throws Exception {

    start();    //call to start

    Thread.sleep(5000);

    stop();     //call to stop

}

Question is: when I run this everything works fine and as expected. However, when I run: ps -ef | grep java it shows that the program is still running in background. Even though the polling service has definitely stopped!

Why does thi开发者_如何学Pythons happen? And what can I do to fix it?


You need to take a thread dump to see which non-daemon threads are still running.

jstack, visualvm or jconsole are a few ways to do this.

You can force the application to stop with

System.exit(0);

As polling is in a daemon thread it won't matter if its stopped or not. The program would finish regardless.


IMHO, you should not roll your own boolean flag. Instead, use the thread's own interrupted status.

while(!Thread.currentThread().isInterrupted()){
    // do stuff
}

If you read the javadoc concerning shutdownNow(), it says

... any task that fails to respond to interrupts may never terminate

I believe this would not be the case if you implemented the above logic. Also, if you perform any blocking operations, you'll need to propagate the interruption to ensure that the thread receives the interrupt.


In your processing, are you catching Exceptions and continuing processing? Are you not allowing the ThreadInterruptException to trickle up and cause the Thread to shut down?

http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow()


If you are seeing that the Java process is alive, it is because there is atleast one daemon thread in the JVM. The API documentation of the Thread class states:

The Java Virtual Machine continues to execute threads until either of the following occurs:

  • The exit method of class Runtime has been called and the security manager has permitted the exit operation to take place.
  • All threads that are not daemon threads have died, either by returning from the call to the run method or by throwing an exception that propagates beyond the run method.

And therefore, this line of code in your ThreadFactory implementation ought to explain why the process continues to be alive:

thread.setDaemon(true);

All Runnable tasks that are submitted to the ExecutorService will now be run as daemon threads. You ought to verify whether the threads that have been initialized have been terminated or not. This also includes the thread that is executes your polling loop (and need not be the main thread, depending on how you've written the Polling class).

If you've reviewed your code and you haven't figure out what section is responsible for the daemon thread to be alive, you adopt one of the following techniques to determine what thread is preventing the JVM from shutting down:

  • Send a SIGQUIT signal to the Java process. This will give you a thread dump of the JVM, with the stacks of all the threads; you will need to redirect stdout to a file, in case your JVM process is running as a background process. In the resulting stack trace, you should find at least one daemon thread that is alive and executing a section of code in your application.
  • Consider setting a name to the threads initiated by the ThreadFactory. This way, should you use a logger that prints out the thread name along with a message at the end of the run method, you can determine whether threads are alive by noting the absence of any messages.


Are you using any blocking queue or any resource? Because how normally it works is that, when you call up shutDownNow(), it throws an interrupt to the thread, if the pool thread hasnt started executing the Runnable, it terminates, if not then it has to wait till the end. Now the point is if you are using a BlockingQueue or Asynchronous I/O with Selector or whatever, each has its own policy of how it deals with interrupts. Say if you used a BlockingQueue, and say it was is waiting for a Runnable, and at the same moment an interrupt is received, then it throws an InterruptedException and the interrupt status is cleared. ie you will have manually let the stack know, that an interrupt was thrown by:

try{
runnable.run();
}
catch(InterruptedException ex)
{
Thread.currentThread.interrupt();//let the stack know that interrupt was thrown.
}

If your case is the above case, without the catch statement, the thread will never terminate, because the interrupt status is cleared as soon as the Exception was thrown. Hence depending on the package you use, check the interruption policy. It will be better if you can provide the code in Polling

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜