javamultithreadingexceptionuncaughtexceptionhandler

Starting a new thread on Exception using Uncaught Exceptional Handler


A runnable task parses incoming xml file and is invoked from a different class. Sometimes the parsing may fail and throw an exception. The task should be running even when exceptions occur. I tried restarting the same task in a new thread using Uncaught exception handler. But wanted more ideas on that.

Class invoking thread : (invokes thread)

It works fine to restart same task in new thread but probably handling exceptions without leading to a thread exit should be the way

    Thread fileProcessThread = new Thread(FileProcessor);

    fileProcessorThread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler()
          {
             @Override
             public void uncaughtException (Thread arg0, Throwable arg1)
              {
                FileProcessor newObject = new FileProcessorTask();
                Thread t = new Thread(newObject);
                t.start();
              }
          });

    fileProcessor.start();

Task Class :

      public void run() {

        try {
              xmlparser.parse(incomingXmlFile);
            } 
            catch (Exception e) {
                Thread.currentThread.getUncaughtExceptionalHandler().uncaughtException(Thread.currentThread(), e); 
                // this invokes uncaughtException to restart thread ?
            }
      }

I have a watch service (file directory scan) running, so I need the task all the time, even if thread terminates.


Solution

  • When an exception occurs and call reaches the uncaughtExceptionHandler, the state of the thread is Invalid to start again. So you need to create a new thread and start again.

    Code from Thread.start()

    // A zero status value corresponds to state "NEW".
    if (threadStatus != 0)
       throw new IllegalThreadStateException();
    

    However this could easily result in an infinite loop. (exception -> catch -> retry -> exception -> catch ...) I recommend having a counter which stops the retries after a certain point.

    Public class TestClass{
        static AtomicInteger counter = new AtomicInteger();
    
        static class MyExceptionHandler implements UncaughtExceptionHandler {
            @Override
            public void uncaughtException(Thread t, Throwable e) {
                System.out.println("caught");
                if (counter.get() == 3) {
                    System.out.println("Reached Max. retries, exiting");
                } else {
                    counter.incrementAndGet();
                    new Thread(new MyTask()).start();
                }
    
            }
        }
    
        static class MyTask implements Runnable {
            @Override
            public void run() {
                try {
                    Thread.currentThread().setUncaughtExceptionHandler(new MyExceptionHandler());
                    System.out.println("slept");
                    Thread.sleep(500);
                    double d = 0 / 0;
                } catch (InterruptedException e) {}
            }
        }
    
        public static void main(String args[]) throws Exception {
            Thread thread = new Thread(new MyTask());
            thread.start();
        }
    }
    

    I've used static AtomicInteger but in your implementation probably have a common object which can be passed on from one thread to another and let that object have a counter.