0

I am writing an Spring-mvc application.

I am executing task using ThreadPoolTaskExecutor.

I have below sample code.

MyClass.java

public class MyClass {
    public void startProcess() {
        ThreadPoolTaskExecutor taskExecutor = //Initializing 
        for (int i = 1; i <= 5; i++) {
            taskExecutor.execute(new MyRunnable());
            // I can call taskExecutor.submit(task); also, if required
        }
    }
}

MyRunnable.java

public class MyRunnable implements Runnable {

    @Override
    public void onRun() {
        try {
            //Code which generates exception like below
            throw new Exception("Runtime Exception");
        } catch (Exception e1) {
            // log or throw the exception
        }
    }
}

I want to notify startProcess() about the exception occurred in MyRunnable's run method.

Can any one please guide me for this.

I found below links but it is not solving my problem.

Thanks.

Edit:

One more question. If I am using @Async for asynchronous call to my some other method and If I want to check for the exception occured in async method then what should I do? As async method also returns future object.

Answer for @Async question I got from here

Community
  • 1
  • 1
Naman Gala
  • 4,670
  • 1
  • 21
  • 55

2 Answers2

1

You can add constructor with some listener to your Thread.

Like:

ExceptionListener:

  public class ExceptionListener{
    public void doSomething(long threadId,Exception e){
      //...e.g., notify startProcess()
    }
  }

MyRunnable:

  public class MyRunnable implements Runnable {
    private ExceptionListener listener;

    private MyRunnable(ExceptionListener exception) {
      this.listener = listener;
    }

    @Override
    public void run() {
      //...
      listener.doSomething(Thread.currentThread().getId(),new Exception("Runtime Exception"));
      //...
    }
  }

startProcess():

  public void startProcess() {
    ThreadPoolTaskExecutor taskExecutor = //Initializing 
    ExceptionListener listener= new ExceptionListener();
    for (int i = 1; i <= 5; i++) {
        taskExecutor.execute(new MyRunnable(listener();
        // I can call taskExecutor.submit(task); also, if required
    }
  }

Or, you can use Thread.UncaughtExceptionHandler, like described here.

edited.

Clarification:

if exception occurs, I have to stop my further execution of other processes. So I want to catch or get notified about the exception in startProcess method. – Naman Gala 1 hour ago

Answer:

I suppose that your worker thread will have while cycle. So you can just pass volatile boolean to each thread and set it up to true or false in case of exception, cycle condition will be this boolean variable. – Maksym 58 mins ago

Community
  • 1
  • 1
Maksym
  • 4,434
  • 4
  • 27
  • 46
  • You mean after calling execute method I should inspect `listener` in `startProcess`? – Naman Gala Dec 08 '14 at 10:51
  • In UncaughtExceptionHandler example, should I pass single object of Thread.UncaughtExceptionHandler to every thread or should I create individual object for every thread? – Naman Gala Dec 08 '14 at 10:53
  • Actually in most cases you should handle exceptions in the same thread. What do you want to achive ? – Maksym Dec 08 '14 at 10:58
  • Should I pass single object of Thread.UncaughtExceptionHandler to every thread or should I create individual object for every thread? -- > You are setting it to the thread object before starting it, like t.setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler); So it's up to you have one for all or different for each... – Maksym Dec 08 '14 at 11:00
  • if exception occurs, I have to stop my further execution of other processes. So I want to catch or get notified about the exception in startProcess method. – Naman Gala Dec 08 '14 at 11:00
  • I suppose that your worker thread will have while cycle. So you can just pass volatile boolean to each thread and set it up to true or false in case of exception, cycle condition will be this boolean variable. – Maksym Dec 08 '14 at 11:05
  • I think Thread.UncaughtExceptionHandler is for handling uncaught exception. It will not notify about the exception. Correct me if I am wrong. Your approach can solve my problem. – Naman Gala Dec 08 '14 at 11:16
1

Instead of Runnable, implement Callable. A Callable can throw an exception, and when you retrieve the result of the Callable using a Future, you will get the exception thrown as an ExecutionException:

public class MyCallable implements Callable<Void> {
    public Void call() throws Exception {
        try {
            //Code which generates exception like below
            throw new Exception("Runtime Exception");
        } catch (Exception e1) {
            // log or throw the exception
        }
        return null; // To satisfy the method signature
    }
}

In MyClass:

List<Future<Void>> futures = new ArrayList<>();
for (int i = 1; i <= 5; i++) {
    Future<Void> future = taskExecutor.submit(new MyCallable());
    futures.add(future);
}

// After all tasks have started, now wait for all of them to complete (they run in parallel)
// and check if there were any exceptions

for (Future<Void> future : futures) {
    try {
        future.get();
    } catch (ExecutionException e) {
        // Access the exception thrown by the different thread.
        e.getCause().printStackTrace();
    }
}
Erwin Bolwidt
  • 30,799
  • 15
  • 56
  • 79
  • Do I need to check for isDone() condition? – Naman Gala Dec 08 '14 at 11:21
  • 1
    No, the `get` method (without a timeout) will already wait until its done. Except if your main thread is interrupted, but in that case you will get an `InterruptedException`. – Erwin Bolwidt Dec 08 '14 at 11:23
  • One more question. I don't know it is related to this or not. If I am using @Async for asynchronous call to my some other method and If I want to check for the exception occured in async method then what should I do? As async method also returns future object. – Naman Gala Dec 08 '14 at 11:26
  • Got my answer for @Async question here (http://stackoverflow.com/a/24337275/3898076). – Naman Gala Dec 08 '14 at 11:43