views:

287

answers:

1

I have a multi-threaded program, where I have one thread to watch over several threads. The functioning is designed like this:

Main program does initiation and starts Watcher Thread, in void Main(), I have the line

Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownThread(), "Exit Listener"));

When I don't start the watcher thread, the ShutdownThread is called when I terminate the program, but when I start the Watcher thread which has a dead loop in it, the ShutdownThread is not called (I print out a message in that thread). That is very very strange. Any explanations?

The watcher thread is like:

public void run(){
   boolean running=false;
   thread a=new thread(...); //Do the same thing for b, c, d...
   while(true){
   if (a.isActive()){
     if (running)
        thread a= new thread(...);
     a.start();
     running=true;
   }
   Thread.sleep(1000); //try catch block...
}

What I would like is a graceful shutdown, that upon getting a terminate signal, shutdownThread is run, sets a flag and interrupts all threads, and waits for the threads to interrupt it, or it timeout so that the remaining threads can be killed. All the threads can catch an interuption, and check if a flag is set, if set, it will interrupt shutdownThread and then exit itself. Instead what I am seeing is all the threads are terminating by itself, doing no cleanup at all.

How about using signals? Is there any good cross-platform code for that?

Then, setUncaughtExceptionHandler doesn't work either. I did testing, and found that the handler isn't called at all. I don't know why. The code for the handler is:

    public static class ErrHandler implements Thread.UncaughtExceptionHandler{
    public final void uncaughtException(Thread t, Throwable e) {
            Error(t + "died, threw exception: " + e);
        }
    }//this is in public class globals

I hook it using

producer.setUncaughtExceptionHandler(Globals.errhandler);

Is in my code, and I only see the original e.printStack() instead. It seems that I can't override it, either in the parent thread, or in itself. This is so frustrating. I'm thinking of putting a Entry into a queue, and reading it elsewhere. At least that may work.

Oh, the whole purpose is to make sure that if any of the threads die because of runtime exceptions, the watcher thread will check whether the exception is fatal enough, and decide to restart that thread or to quit altogether. At the same time, I would like the program to end gracefully (an interrupt is sent to saver threads so that it dumps the results out, and then interrupts back to tell that we are ready to quit) when the user ends it.

A: 

Dunno if it helps you, but we encountered the same behaviour. Not all exceptions are routed correctly to the registered ExceptionHandler.

I wonder if Unit-Tests exists at all for the concurrent framework. Because this had to be detected.

We implemented the ScheduledExecutorService by ourself by using a ScheduledExecutorService instance as delegate and encapsulate the parameter Runnable/Callable of each method in a Runnable/Callable implementation which corrects the behaviour.

pimpf0r