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();
Related
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.
I'm new to RX and i don't know how the schedulers work. below is some code that never run onComplete . but if i put a while(true) loop at the end it works correctly. it seams the app will exit before running new thread.
why is this happening? and how to fix this issue?
Subscriber<String> subscriber = new Subscriber<String>() {
#Override
public void onCompleted() {
System.out.println("done");
}
#Override
public void onError(Throwable throwable) {
}
#Override
public void onNext(String o) {
System.out.println(o);
}
};
Observable.from(new String[]{"1", "2", "3","4"}).
subscribeOn(Schedulers.immediate())
.observeOn(Schedulers.newThread())
.subscribe(subscriber);
Just add Thread.sleep(1000); as the last statement if your program exits too early.
As to why this happens.
This answer quotes:
The Java Virtual Machine continues to execute threads until either of the following occurs:
...
All threads that are not daemon threads have died ...
Now if we look at RxThreadFactory that produces threads for Schedulers:
public final class RxThreadFactory extends AtomicLong implements ThreadFactory {
...
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, prefix + incrementAndGet());
t.setDaemon(true);
return t;
}
}
So a more complex solution would be to use Schedulers.from() and pass in a custom Executor with your own ThreadFactory that produces non-daemon threads.
My consumer doesn't work the way I expect it to. Below is an sscce of what happens in my real program.
Expected:
Print In finally!
Print About to print stacktrace
Print a NullPointerException stacktrace.
Actual:
Print In finally!
Hang, in sun.misc.Unsafe
Program:
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
public class ThreadTest implements Runnable {
public static void main(String... args) {
ExecutorService service = Executors.newSingleThreadExecutor(new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
Thread newThread = new Thread(r);
newThread.setUncaughtExceptionHandler(new MyExceptionHandler());
return newThread;
}
});
service.submit(new ThreadTest());
}
private static class MyExceptionHandler implements UncaughtExceptionHandler {
#Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("About to print stacktrace");
e.printStackTrace();
}
}
#Override
public void run() {
Object foo = null;
try {
while(!Thread.interrupted()) {
Thread.sleep(1000);
System.out.println(foo.toString());
System.out.println("After npe!");
}
} catch(InterruptedException e) {
} finally {
System.out.println("In finally!");
}
}
}
Runnables run inside an Executor don't really throw exceptions which will hit the thread's uncaught exception handler. Instead, the Runnable is wrapped with code which catches Throwable. This is so that a Future can return the exception that was thrown from the task.
as #Gray noted in the comments below, your program is "hanging" because the thread pool thread is keeping the program from exiting. your runnable has completed and the thread pool thread is just waiting for a new task. if you shutdown the thread pool, your program will complete normally (or make the thread pool threads daemon).
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
}
}
}
I have the following code that I expect to run successfully to completion but the code fails at the line "fail("this should not be reached");". Can someone please explain why the default uncaught exception handler is not called:
public class UncaughtExceptionTest extends TestCase
implements UncaughtExceptionHandler {
private final List<Throwable> uncaughtExceptions =
new CopyOnWriteArrayList<Throwable>();
class UncaughtExceptionTestInnerClass implements Runnable {
private final ScheduledThreadPoolExecutor executor =
new ScheduledThreadPoolExecutor(1);
private final CountDownLatch latch;
UncaughtExceptionTestInnerClass(CountDownLatch latch) {
this.latch = latch;
executor.schedule(this, 50, TimeUnit.MILLISECONDS);
}
#Override
public void run() {
System.out.println("This is printed");
fail("this should fail");
latch.countDown();
}
}
#Test
public void testUncaughtExceptions() {
Thread.setDefaultUncaughtExceptionHandler(this);
CountDownLatch latch = new CountDownLatch(1);
UncaughtExceptionTestInnerClass testTheInnerClass =
new UncaughtExceptionTestInnerClass(latch);
try {
if (!latch.await(1, TimeUnit.SECONDS)) {
if (uncaughtExceptions.size() > 0) {
Throwable exception = uncaughtExceptions.get(0);
System.out.println("First uncaught exception: " +
exception.getMessage());
}
else {
fail("this should not be reached");
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public void uncaughtException(Thread t, Throwable e) {
uncaughtExceptions.add(e);
}
}
It has to do with the fact you're using an Executor to run the task. The uncaught exception handler is invoked only if the thread is about to be terminated due to an uncaught exception. If you change your implementation to use a plain thread so that the thread will terminate with the exception, you will see the expected behavior.
Depending on how you submit tasks, the executor thread may catch all Throwables and handle them. Therefore, the thread does not terminate due to these exceptions, and thus the uncaught exception handler does not get involved. For example, ThreadPoolExecutor.execute(Runnable) will trigger the uncaught exception handler. However, ThreadPoolExecutor.submit(Callable) does not. Also, ScheduledThreadPoolExecutor.schedule() does not either (it has to do with their use of FutureTask for implementation).
A better way of accessing unexpected exceptions with an executor service is via Future.
ScheduledThreadPoolExecutor.schedule() takes a Runnable/Callable argument, not Thread. The former don't have runtime exception handlers. Have a try/catch block for a RuntimeException in your run or call method.