The core problem is that you're killing your threads by calling System.exit(), rather than having them shutdown cleanly. This means they may keep running very briefly after everything else is closed but before the JVM actually ends the process, and if they use any shared state during that time (e.g. the logging system), it could be in an inconsistent or broken state as it may have been shutdown. This is not good practice (see http://www.javapractices.com/topic/TopicAction.do?Id=86).
The way to solve this is to properly shutdown your threads before shutting down shared resources (the logging system). Instead of just calling system.exit(), tell each thread that it's time to stop, and wait from them to do so. The cleanest way to do this is to have them check a running
boolean on each loop, and to set that boolean to false externally when you want the loop to stop. You can then wait for the thread to notice this boolean and terminate by calling Thread.join() on the given thread instance, or by having the thread set some finished
boolean when it's done (best to mark both these booleans as volatile).
If each iteration of your loop takes sometime, or contains wait()
or sleep()
calls you should look at checking the running boolean more often during the loop, or using Thread.interrupt()
.
Once this has finished and you're sure every other thread has stopped, you can then call LogManager.shutdown()
and actually terminate your process.