Reexecute task from within UncaughtExceptionHandler? - java

I've seen some discussions along these lines, but not a specific answer to my question. I want to restart a task when a thread dies due to an uncaught exception. Is it safe to call pool.execute(runnable) from within the UncaughtExceptionHandler set on the dying thread?
Ideally, if the throwable is a RuntimeException, I'd like to just resubmit the runnable to the pool, e.g.
pool = Executors.newFixedThreadPool(monitors.size(), new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
threadMap.put(thread, (Monitor)r);
thread.setName(((Monitor)r).getClusterName() + "-monitor");
thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread th, Throwable t) {
logger.error("Uncaught exception in thread: " + th.getName(), t);
if (t instanceof RuntimeException) {
Monitor m = threadMap.get(th);
if (m != null && m.runCount() < restartMax) {
logger.error("Restarting monitor due to uncaughtException: " + m.getClusterName());
pool.execute(m);
} }
}
});
return thread;
}
});
Is there a better way or safer way to do this?
Thanks!

The safest option would be to only throw an Runtime Exception which it is fatal. If a Runtime Exception can be safely ignored why is it not being caught and continued?
It appears that your thread map is like a ThreadLocal, it appears that once one task uses all your restartMax, it will never restart a task again?
The way I would do this is to wrap the executing Runnable.
public void submit(final Runnable runnable, final int restartMax) {
pool.submit(new Runnable() {
public void run() {
for(int i=0;i<restartMax;i++)
try {
runnable.run();
break;
} catch (Exception e) {
log.error("Exception", e);
}
}
}
}

Your code sample won't do the job you're trying to address. The runnable that gets passed to the ThreadFactory is not your task runnable but an internal runnable that is used by the ThreadPoolExecutor.
You may want to consider overriding the afterExecute() method instead. This method will always be called, and the first argument will be your runnable, and the second (Throwable) argument will contain the uncaught exception. However, afterExecute() will not report the exception if the task is wrapped either explicitly by you with a FutureTask or indirectly via submit(). So, afterExecute() would work only with submission via execute().
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t != null) {
Monitor m = (Monitor)r;
if (m.runCount() < restartMax) {
logger.error("Restarting monitor due to uncaughtException: "
+ m.getClusterName());
execute(m); // exception handling omitted
}
}
}

Related

ExecutorService.awaitTermination() returns true, even if tasks aren't finished

Here is my parser class:
public class InputFilesParser {
private ExecutorService executorService;
private volatile Throwable thrownError;
public InputFilesParser(int poolSize) {
this.executorService = Executors.newFixedThreadPool(poolSize, (r) -> {
Thread t = new Thread(r);
t.setUncaughtExceptionHandler((thread, e) -> {
//this should be called before the thread has finished.
this.notifyOnException(thread, e);
});
return t;
});
}
}
public void parseFile(Path inputFilePath) throws Throwable {
//if exception is set, then no more files will be processed.
if (this.thrownError != null) {
//execution will stop here because an error will be thrown from waitToFinish()
this.waitToFinish();
}
this.executorService.execute(() -> {
//this will always throw an exception which have to be handled by the above mentioned uncaughtExceptionHandler.
this.processFile(inputFilePath);
});
}
private void processFile(Path inputFilePath) {
throw new RuntimeExecption();
}
public void waitToFinish() throws Throwable {
this.executorService.shutdown();
while (true) {
try {
//if statement will be entered only when awaitTermination returns true, meaning all the tasks are finished.
if (this.executorService.awaitTermination(STOP_CHECK_TIMEOUT, TimeUnit.SECONDS)) {
synchronized (this) {
//in this scenario, after all tasks are finished, the thrownError should be set
if (this.thrownError != null) {
//I expect to get this output
System.out.println("Exception: " + this.thrownError);
throw this.thrownError;
}
//but I get this output
System.out.println("No exception: " + this.thrownError);
}
break;
}
} catch (InterruptedException e) {
LOG.info("An interruption occurred", e);
}
}
}
private synchronized void notifyOnException(Thread thread, Throwable t) {
//if the thrownError isn't set, then set it here so that waitToFinish() will know that an error occurred.
if (this.thrownError == null) {
this.thrownError = t;
}
}
}
on the calling thread, I have the following:
InputFilesParser ifp = new InputFilesParser(poolSize);
try {
for (Path f : files) {
//each parsing will throw an exception in this scenario
ifp.parseFile(f);
}
//an exception should be detected and the error thrown, but actually this is not happening, but printing No exception... message.
ifp.waitToFinish();
catch(Exception e) {
e.printStackTrace();
}
Although there is an exception thrown, the calling thread gets in waitToFinish() method, printing null for the thrown exception:
Thread: Thread-5. No exception: null
This means that awaitTermination returns true, before the exception is set in notifyOnException method. But notifyOnException method is called from a thread run by this executor service. In my opinion there is a problem with my understanding, or there is a problem with java.
Any idea which one of this :) ? In my opinion, this shouldn't be possible. Am I missing something about setUncaughtExceptionHandler method and the way how it handles the exceptions? Although from documentation it seems that this method is called by the thread throwing the exception.
public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh)
Set the handler invoked when this thread abruptly terminates due to an uncaught exception.
A thread can take full control of how it responds to uncaught exceptions by having its uncaught exception handler explicitly set. If no such handler is set then the thread's ThreadGroup object acts as its handler.
Parameters:
eh - the object to use as this thread's uncaught exception handler. If null then this thread has no explicit handler.
Thanks in advance.
It seems to me that my assumption in regard to UncaughtExceptionHanlder's method call is wrong.
Java docs says this:
public static interface Thread.UncaughtExceptionHandler
Interface for handlers invoked when a Thread abruptly terminates due to an uncaught exception.
When a thread is about to terminate due to an uncaught exception the Java Virtual Machine will query the thread for its UncaughtExceptionHandler using Thread.getUncaughtExceptionHandler() and will invoke the handler's uncaughtException method, passing the thread and the exception as arguments.
With other words, it is not the thread itself which calls the UncaughtExceptionHandler's method, but JVM. This means that there is no constraint in regard to the order of operations when awaitTermination is called.

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.
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.

Java - How to 'return' a value in a class

I am trying to assign a value or return a value in a class. Something like this:
void setOff() {
boolean onValue = true;
Thread t = new Thread(new myClass(onValue));
System.out.println("On: " + onValue);
}
class myClass implements Runnable{
public boolean on;
public myClass (boolean _on) {
on = _on
}
public run() {
on = false;
}
}
Is something like that possible? Thanks!
It is possible, but you need to change your code a bit. Check the following classes:
Callable<V>
FutureTask<V>
The first one is something like a Runnable, but the method you need to implement is defined as V call() throws Exception, instead of void run(): it allows you to return a value.
The second one wraps a Callable<V> (or a Runnable plus a constant return value), and is a Runnable itself, so you can pass it to a Thread just like you were doing with your Runnable.
So, you could change your code to something like the following:
void setOff() {
final FutureTask<Boolean> ft = new FutureTask<Boolean>(new myClass());
new Thread(ft).start();
try {
System.out.println("The result is: " + ft.get());
} catch (ExecutionException e) {
System.err.println("A method executed on the background thread has thrown an exception");
e.getCause().printStackTrack();
}
}
class myClass implements Callable<Boolean> {
#Override public Boolean call() throws Exception {
// let's fake some long running computation:
Thread.sleep(1000);
return true;
}
}
The call ft.get() will only return after the call() method finishes executing (on the background thread), so you will have to wait 1 second before the line gets printed to the console.
There are many other useful methods on FutureTask. Check the documentation.
There are some other classes that you may find useful: ExecutorService and its implementations, and the factory methods in Executors. It has a method called submit which accepts a Runnable or a Callable<V>, and returns a Future<?> or Future<V>, which is one of the interfaces implemented by FutureTask. You get a similar behaviour. For example:
public static void main() {
final ExecutorService es = Executors.newCachedThreadPool();
final Future<Boolean> f = es.submit(new myClass());
try {
System.out.println("The result is: " + f.get());
} catch (ExecutionException e) {
System.err.println("A method executed on the background thread has thrown an exception");
e.getCause().printStackTrack();
}
es.shutdown();
}
The advantage of this is that the ExecutorService will manage the threads for you. It may create some threads and reuse them for the Callables and Runnables you submit: this will possibly improve performance if you have many such jobs, since you will avoid creating one thread per job -- thread creation has some overhead!
EDIT: the .get() method throws an ExecutionException, which wraps an exception that might get thrown during the execution of the .call() method. To inspect the exception, catch the ExecutionException and call .getCause() on it. I've just added the missing try/catch block.

Efficient exception handling for threads in java

How do we implement efficient exception handling when using threads.
I have a main program which creates 3 threads. How do we handle the exceptions for the exceptions thrown during the execution of thread?
Can we use the try/catch block or uncaughtexception. If so, can you please share some samples.
public class MyThreadTest {
public static void main(String[] args) {
Thread newThread = new Thread(new ThreadWithException());
// Add the handler to the thread object
newThread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler(){
#Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("ERROR! An exception occurred in " + t.getName() + ". Cause: " + e.getMessage());
}
});
newThread.start();
}
}
/**
* This thread throws a custom exception in its run method.
*/
class ThreadWithException implements Runnable {
#Override
public void run() {
throw new RuntimeException("Application Specific Exception!!");
}
}
Either you can use:
Thread#setUncaughtExceptionHandler to specify some code that is run when an exception is thrown (outside of normal program flow), or:
ExecutorService#invokeAll to run all of your blocks, and inspect the returned list for Future#get()'s throwing of ExecutionException. Another option is CompletionService, but this is slightly harder to use for such a simple case.
You can use try / catch block strategy:
Thread t = new Thread() {
#Override
public void run() {
try {
//..thread code
} catch (Exception e) {
}
}
};
It is easy to implement but in case of exception main thread of your application will never know what happened inside of child thread.
Better method would be to spawn threads using ExecutorService (as mentioned by FauxFaux). This will allow you to easily pass information about the error to main thread. Besides that, using ExecutorService allows you to write less code. You won't have to manage threads in your code but leave it for ExecutorService instead.
beacuse , recently, I have write a program with about 3 threads in order to fill a lot data from mysql and mongoDb to ElasticSearch. I share u my code.
I use java.util.concurrent.Executors.
First I have a main class. It calls
public void start() throws Exception {
this.logger.info("Main: Start the worker manually");
schedulerThreadPool = Executors.newScheduledThreadPool(this.maxNumberOfThread);
for (int i = 0; i < this.maxNumberOfThread; i++) {
Worker worker = new Worker();
long delay = i * this.sleepBetweenTaskStart;
schedulerThreadPool.scheduleAtFixedRate(worker, delay, this.minTimeBetweenEachTask, TimeUnit.MILLISECONDS);
}
}
And Worker implements Runnable and get Thread Id by below code.
this.threadId = Thread.currentThread().getId();
And just try catch in each Worker. Everything works normally.
#Override
public void run() {
try {
do...
} catch (Exception e) {
e.printStackTrace();
}
}

Thread.setUncaughtExceptionHandler does not work

I set thread's uncaughtExceptionHandler as shown in the code below but it does not work when a HibernateException is raised in the thread running. My jvm is 1.6.0_26. Any clue?
this.executor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory()
{
public Thread newThread(Runnable r)
{
Thread result = Executors.defaultThreadFactory().newThread(r);
result.setUncaughtExceptionHandler(new UncaughtExceptionHandler()
{
public void uncaughtException(Thread t, Throwable e) {
logger.error("error occurs while supervior is running", e);
}
})
return result;
}
});
I am not seeing where you actually started the thread. Don't you need to run the thread for this code block to work? Such as:
// execute Threads run method
result.start();

Categories

Resources