A common mistake when creating threads is to use the non-daemon variety that will cause the JVM to keep running even when System.exit() is called. The default constructor for Thread creates a “user” thread, which is often not the behaviour expected by the programmer.  User threads are designed for important tasks which should not be arbitrarily stopped, like finishing a credit card transaction.

“The Java Virtual Machine exits when the only threads running are daemon threads”.  

The following main( ) function will never finish.

public static void main(String[] args)
{
    Thread worker = new Thread()
    {
        public void run()
        {
            for (;;)  // ever
            {
               FileSystemManager.process();
               try {Thread.sleep(10000L);} catch (Exception e) {}
            }
        }
    };
    worker.start();
    DataManager.processUntilComplete();
}

The above code will never finish but not because of the for(;;)loop. A single line to setDaemon(true)  added before the start( ) allows main( ) to exit when completed:

public static void main(String[] args)
{
    Thread worker = new Thread()
    {
        public void run()
        {
            for (;;)  // ever
            {
               FileSystemManager.process();
               try {Thread.sleep(10000L);} catch (Exception e) {}
            }
        }
    };
    worker.setDaemon(true);
    worker.start();
    DataManager.processUntilComplete();
}

The useful Timer class has the same unexpected problem: by default it creates a user thread instead of a daemon thread.

// Repeatedly check for a new configuration file:
appTimer = new Timer();
appTimer.scheduleAtFixedRate
(
   new TimerTask()  
   {
       public void run()  
       {
           try
           {
               checkRefreshConfiguration();
           }
           catch (Exception e)
           {
              logger.error("Invalid configuration", e);
           }
       }
   }, RELOAD_DELAY_MSECS, RELOAD_PERIOD_MSECS
);   

This timer thread had a worse effect, in that it prevented the web application from shutting down.  The timer thread could be easily fixed, as below:

// Repeatedly check for a new configuration file:
appTimer = new Timer(true);
appTimer.scheduleAtFixedRate
(
   new TimerTask()  
   {
       public void run()  
       {
           try
           {
               checkRefreshConfiguration();
           }
           catch (Exception e)
           {
              logger.error("Invalid configuration", e);
           }
       }
   }, RELOAD_DELAY_MSECS, RELOAD_PERIOD_MSECS
);   

Tip: Use only Daemon threads for general development. You need a pretty specific reason to use Non-Daemon threads.

blog comments powered by Disqus