Question

The code I've inherited is a server that spawns many different types of daemon threads that receive and respond to requests as they come in. Obviously, this is dangerous and needs to be refactored away. As it is now if the main program is halted while one of the daemons is servicing a request the thread could be killed midway through the request and leaving something in an inconsistent state.

However, there are quite a few threads spread through different areas of the code. If I had to manually close every one of the threads when a shutdown is called, well it could be a bit of a pain to get logic flow perfect without missing some obscure daemon.

What I would like to do instead is to have a thread that is like a daemon thread, but I can mark or toggle some section of the thread as a critical section; which will complete the therad from being reaped until it completes. While the daemon is blocking and waiting for requests it behaves like a daemon thread, doesn't prevent the VM from closing, and will be stopped immediately if the VM is shutting down. However, while the thread is actively servicing a specific request (a fraction of the time the thread is active) the thread will not be killed until it completes and exits it’s critical section. Once the thread finishes it's critical section it then becomes eligible to be killed. Ideally when no more non-daemon threads are available the VM would start it’s shut down process immediately, even if some daemons are still doing critical work, by reaping any daemon not in a critical state and then wait for each remaining 'daemon' to exit it's critical point so it could be killed.

Is there an easy way to get this behavior just by instantiating a Thread class (possibly one I write) or setting a Boolean, rather than having to explicitly write each thread to properly handle interrupts to behave like this? I'm looking for a mostly idiot proof way so that if plugins, running in such a thread, are not written to handle interrupts perfectly the thread will still properly complete it's critical section and then exit when the VM is shutting down.

Was it helpful?

Solution

However, there are quite a few threads spread through different areas of the code. If I had to manually close every one of the threads when a shutdown is called, well it could be a bit of a pain to get logic flow perfect without missing some obscure daemon.

Unfortunately the best way to do this is as you imply. You should have a destroy() method on the classes that fork threads so they can explicitly clean up after themselves. But this does require someone calling those destroy methods when the application is terminating.

What I would like to do instead is to have a thread that is like a daemon thread, but has a certain critical section where it cannot be killed until it completes (or maybe times out if it takes too long?).

There is nothing in the Java threads that allows this behavior. Either a thread is daemon or it is not and this is set before the thread starts.

Is there an easy way to get this behavior just by instantiating a class or setting a Boolean

I think you are on to something here. I would have a ThreadUtils class with a volatile boolean shutdown field.

 public class ThreadUtils {
     private static volatile boolean shutdown = false;
     /** called by main when the application is shutting down */
     public static void shutdown() {
         shutdown = true;
     }
     /** used by the various non-daemon threads to test for shutdown */
     public static boolean isShutdown() {
         return shutdown;
     }
 }

You main program would set the shutdown flag to true and then all of your threads would need to check this boolean in their code:

 // we can test for shutdown only at "appropriate" points in the thread
 while (!ThreadUtils.isShutdown()) {
     ...
     // we are not ready to be killed here
     ...
 }

Something like this pattern, although a bit gross, sounds like it fulfills your requirement.

OTHER TIPS

I am trying to improving last answer by @Gray.

You can maintain a counter of currently running threads. Every new thread starting will increment this counter and every thread completing run() will decrement it. Then you can add a shutdown hook in your main thread by using API Runtime.addShutdownHook() . When java process is signaled to quit, this hook will set the condition for global flag ThreadUtils.isShutdown() to true and wait for all running threads to complete work and die naturally when all threads have exited.

To prevent indefinite wait, you can have a timeout inside shutdown hook's run() method. If timeout occurred, run() will terminate immediately resulting in all daemon threads to terminate too.

So all these daemon threads are event loops processing requests. What if you simply send a shutdown request to all of them, so they can exit cooperatively. Each thread probably has an ad hoc way of polling request from somewhere, so you'll need to refactor them a little.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top