Catching exceptions from another threads? - java

I am writing an app that will make use of multiple threads. There is main thread that is launching another threads. What i want to acomplish is when one of the launched threads throws an exception, the main thread should stop launching threads. It looks more or less like this:
class SomeClass {
boolean launchNewThread = true;
public static void main() {
while (launchNewThread) {
try {
AnotherClass.run();
} catch (CrossThreadException e) {
launchNewThread = false;
}
}
}
}
class AnotherClass implements Runnable {
public void run() {
if (a=0) throw new CrossThreadException();
}
}

You should do it yourself - catch the exception and pass it somehow into the launching thread.
Also, there is Future concept, which does it already. You should launch your threads as futures and check isDone(), and catch ExecutionException from get(), this exception will be thrown if a future's task thrown an exception.

You can also use a listener as described in How to throw a checked exception from a java thread?
When an exception is thrown inside one of the child threads, you could call a method like listener.setLaunchNewThread(false) from the child thread which will change the value of your boolean flag in the parent thread.
On a side note, calling AnotherClass.run() does not start a new thread but only call the run method from AnotherClass within the same thread. Use new Thread(new AnotherClass()).start() instead.

Related

Stopping a Thread / Threads calls interrupt on itself after crash?

I am currently running a Thread from a Service to do some background work.
Now there is the possibility that the Thread crashes or I want to
interrupt the thread from the Service. So how am I supposed to:
stop the Thread realiable, (hard)
catch exceptions and call the Service about the crash
handle InterruptedException if interrupted while sleep()
is Thread.isInterrupted a good way to detect if the Thread stopped?
What I have done so far is the following:
#Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
doMyBackgroundWork();
sleep();
}
}catch(Exception e){
ExceptionHandler.logAndSendException(e);
Thread.currentThread().interrupt();
if(crashedListener != null){
crashedListener.onThreadCrashed();
}
}
LOG.i("Thread stops now.");
}
private void sleep() {
try {
sleep(frequency);
} catch (InterruptedException e) {
//what to do here? it can happen because I stopped it myself
}
}
So at first I am running my Thread until it gets interrupted.
If any exception occurs, I want to start a new Thread, therefore
my Service implements a listener interface and I call it, once an
Exception is thrown. I know that catching everything is discouraged,
but I need to know if the Thread stops, without polling Thread.isAlive()
all the time.
Additionally to my four questions above:
is my code reliable and does what I need?
is it ok to call interrupt on the Thread itself?
Thanks!
You are not actually interrupting your own thread because the catch block is outside of the while loop. Therefore, any exception would stop execution immediately.
Interruption is essentially just a request (usually from another thread) to stop doing what you are doing. The thread is free to ignore it and keep doing what it is doing. Normally you have to throw an exception in response to an interrupt, or stop execution some other way such as just breaking from the loop (you need this around the //what to do here? comment). It so happens that some library methods are "responsive to interruption" meaning they will throw an exception if the thread is ever interrupted, such as Thread.sleep(), which you will most likely have in your sleep call.
I recommend picking Java Concurrency In Practice. Among the excellent concurrency material, there is a chapter on interrupts which is very helpful.
EDIT:
I would remove the code where you interrupt your own thread. You will also need to rethrow the InterruptedException as a runtime exception to get out of the execution loop. Usually people will create a new Exception that extends RuntimeException that is something like MyInterruptedException. You can then add it to the catch block around your loop so that you know when the thread was interrupted vs execution failed.
As a general example you can do something like this:
public void run() {
try {
while (true) {
// check for interrupts in the loop, or somewhere in the work method
if (Thread.interrupted()) {
throw new MyInterruptedException("Important thread interrupted.");
}
doMyBackgroundWork();
sleep();
}
}
catch(Exception e){
ExceptionHandler.logAndSendException(e);
if(crashedListener != null){
crashedListener.onThreadCrashed();
}
}
catch(MyInterruptedException i) {
LOG.i("Execution stopping because of interrupt.");
}
}
private void sleep() {
try {
sleep(frequency);
} catch (InterruptedException e) {
throw new MyInterrptedException(e);
}
}
we have a nice and effective method called stop()(Thread.stop(void):void) which is deprecated, but it works and it's lovely.
Note that stop() throws ThreadDeath at the target thread which is not an exception(and it could any other throwable too), but an Error, so your code will not catch any signal about this.
public void run() {
try {
while (<<using_a_volatile_bool_type_is_better>>) {
...
}
}catch(Throwable t){/**/}/*use throwable instead of exception.*/}
}
Beside dear friend stop() we also have pause() method too, and it really pauses the target thread.
Not just one solution out there, but if it's really critical to keep thread run and run the emergency(or itself) just after any crash, you may run it as a separately app/process, plus get progress status(if any) that ensures you the target thread/app is not freezed(blocked,...)

Java Exeutor framework's exception handling

I wrote an android app for killing background running processes which is performed in a background thread. And I use below class to create my own simple thread framework.
public final class ThreadPool {
private static final ExecutorService sES = Executors.newCachedThreadPool();
public static Future<?> runNow(Runnable task) {
return sES.submit(task);
}
}
However, a serious problem occured. That is the exception(unchecked exception) would be consumed by Executor framework quitely. So I don't know why the ActivityManager.killBackgroundProcesses() method does not work. After spending 2 or 3 hours and I wrote some log at almost every method invoke point, I found this method requires android.permission.KILL_BACKGROUND_PROCESSES permission, otherwise, it would throw a SecurityException that is an unchecked exception. The key is this exception is consumed by Excecutor framework, so I cannot see any exception information at logcat and the app does not crash at all and runs weird.
Of course, I don't know that at first, so I spent a lot of time to find out that reason, mainly depending on two posts:
Handling exceptions from Java ExecutorService tasks and
Catching thread exceptions from Java ExecutorService
So I changed the my ThreadPool class as:
public final class ThreadPool {
private static final ExecutorService sES = Executors.newCachedThreadPool();
/*
* submit(Runnable) and execute(Runnable) method has
* big difference. Especially in Exception handling!!!
* You have to pay attention.
*/
public static Future<?> submitNow(Runnable task) {
return sES.submit(task);
}
public static void executeNow(Runnable task) {
sES.execute(task);
}
}
But I still have below question:
Why Sun/Oracle decide to consume the exception instead of transfer to users to handle if submit(Runnable command) method is used?
How can I change this behavior to handle unchecked exception according to my own need if I insist using submit() method?
And my doubts are:
If submit(Runnable command) method is used, I know the exception result can be get by Future.get() method. But, if we use Future.get() method to judge if an exception occured, the thread Future object located in would be block. That is not what we expect in most case, I suppose.
I also learned Executor.execute() method handles exception like common Thread.start(). But there is no return value. So the task cannot be shut down at any time. Users have no ability to shut down any running thread by Future.cancel() method when leaving activity.
If you call get() on the future, you will get an ExecutionException if the underlying operation (callable) threw an exception. See the docs.
You can't change this behavior (from point 1. )
The reason why this is implemented this way is the following: submit is a non blocking call. The job gets posted in the executor and executed at a later time.
Only when the job is executed do you know if it crashed or not, so only when you try to access the result of the job do you get the exception.
Finally, I find a good solution.
We can extend Thread and invoke setUncaughtHandler() in the constructor like below.
public class MyThread1 extends Thread {
public MyThread1(Runnable task) {
super(task);
setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("thread throws an uncaught exception at thread id: " + t.getId());
}
});
}
}
And then customize a ThreadFactory like following.
public class MyThreadFactory1 implements ThreadFactory {
#Override
public Thread newThread(Runnable r) {
return new MyThread1(r, "Peace");
}
}
So we can call the factory method in Executors like following.
ExecutorService es = Executors.newSingleThreadExecutor(new MyThreadFactory1());
So we can detect the uncaught exception happened in thread.
In a threaded environment, unchecked exceptions are known to be notorious and weird behaviors could occur like threads dying, no exception log etc.
One good way is to wrap the runnable object in a thread. Create a thread group and add the thread to the thread group.
final ThreadGroup group = new ThreadGroup("<a name for the thread group>");
public static Future<?> submitNow(Runnable task) {
//Create a thread wrapping the runnable task and specify the thread group
Thread t = new Thread(group,task);
return sES.submit(task);
}
The ThreadGroup class has its uncaughtException(Thread, Throwable) method which is automatically called by the JVM if a thread encountered an exception and is uncaught in your code. See http://developer.android.com/reference/java/lang/ThreadGroup.html
You can also change the behavior by creating your own ThreadGroup object and overriding the uncaughtException method:
public class MyThreadGroup extends ThreadGroup {
#Override
public void uncaughtException(Thread t, Throwable e) {
//do what you need to do to handle the exception
}
}
Or you can assign an UncaughtExceptionHandler to the current Thread.
public class MyUncaughtExceptionHandler implements UncaughtExceptionHandler {
#Override
public void uncaughtException(Thread t, Throwable t2) {
//Implement
}
}
Thread.currentThread().setUncaughtExceptionHandler(new MyUncaughtExceptionHandler());
Or set the default exception handler:
Thread.setDefaultUncaughtExceptionHandler(new MyUncaughtExceptionHandler());

Executors vs threads

I am trying to run the following piece of code:
public static void main(String[] args){
ScheduledExecutorService service = new ScheduledThreadPoolExecutor(2);
Runnable r = new Runnable() {
#Override
public void run() {
throw new RuntimeException();
}
};
service.execute(r );
ScheduledFuture<?> schedule = service.schedule(r, 0, TimeUnit.SECONDS);
new Thread(r).run();
}
Regarding the above I have the following questions:
Is there any way to catch and respond to exceptions happening on the executor's thread?
Why is the exception from the thread created explicitly propagated to the main thread, but both executions using the executor service does not propagate that error? How can this error ever be discovered?
EDIT: One further question came to mind:
How can i stop a given periodic task that I schedule, let's say after N repeats or N minutes?
Question 2 is really easy - you're not actually starting a new thread, you're just calling run(), which runs synchronously in the original thread. You should be calling start(), at which point the exception won't be propagated back.
As for handling exceptions in a ScheduledExecutorService - if you call Future.get(), it will throw ExecutionException if the original task threw an exception, exposing the original exception as the cause:
Exception thrown when attempting to retrieve the result of a task that aborted by throwing an exception. This exception can be inspected using the Throwable.getCause() method.
If you need to respond to exceptions without blocking for the future to complete, you could wrap your "real" Runnable in another one which just delegated to the original's run() method, but with an appropriate try/catch block.
You can catch it like this:
ScheduledFuture<?> schedule = service.schedule(r, 0, TimeUnit.SECONDS);
try {
Object get = schedule.get();
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (ExecutionException ex) {
ex.printStackTrace();
}
If the code running in (Scheduled)ExecutorService throws an exception it will be rethrown upon calling Future.get() wrapped into ExecutionException
EDIT:
about stopping scheduled tasks, it has been discussed and solved already.

Get exception from threads in java

I have a question with my code.
I have two threads running from the main method & I want to catch the exception that can occur in any of the two threads in the main method.
Future<Object> incoming=Executors.newSingleThreadExecutor().submit(new Task1(param1));
Future<Object> outgoing=Executors.newSingleThreadExecutor().submit(new Task2(param2));
Problem is that if i use Future Object & call get() method for the exception, it will block my code & i would not know if say thread 2 has finished/throws exception before thread 1.
How can i handle this elegantly instead of this?
while(!(incoming.isDone() || outgoing.isDone())){}
I would process the exception asynchronously if you want to deal with as soon as it happens and not wait for any other tasks to finish.
ExecutorService oneService = ...
oneService.submit(new Runnable() {
public void run() {
try {
new Task(param1).run();
} catch(Exception e) {
// handle exception asynchronously
}
}
});
How about this:
A queue shared between all threads (make sure to be thread safe!),
Queue<Throwable> exceptionsToProcess;
Then, lock up your main method with a while loop:
//start threads, pass them the queue
while(true)
{
Throwable t;
while((t = exceptionsToProcess.poll()) == null);
//process t
}
The exceptions will be processed in the correct order, although your run the risk of a ConcurrentModificationException if you're not careful about thread safety.
Edit: This might be a useful queue class for this purpose: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/LinkedBlockingQueue.html

How do I test this method's expected behavior in Java: it spawn a thread, and throws an exception under certain conditions

Suppose that I have a method which spawns a new thread and do some work. Under certain conditions, the newly spawn thread would throw a certain type of exception, which terminates the entire process. I would like to write JUnit tests to verify this behavior. Is there a way to do it?
The method is:
private void foo() {
new Thread() {
#Override void run() {
throw new CertainException("exception messages");
}
}.start();
}
In test (conceptually):
public testExceptionThrownFromNewThread() throws Exception {
try {
foo();
Thread.sleep(5000); // wait for the exception to be thrown
fail();
} catch (CertainException e) {
assertEquals(e.message, "exception messages");
}
}
This test doesn't work because the exception spawn from the other thread cannot be caught.
If you want to test just the code inside of the run() method, refactor it ouf of the foo() method (probably into a Runnable) and test it separately without running it from a thread.
private void foo() {
new Thread(new MyRunnable()).start();
}
public class MyRunnable implements Runnable {
public void run() {
....
}
}
Now you can instantiate a MyRunnable object and call the run() method from your test without needing to start a thread.
EDIT
Testing of the thread creation could be done by using a ThreadFactory Mock. (as Jon Skeet pointed out).
You could overwrite the default UncaughtExceptionHandler for Threads. It gets called whenever a Thread throws an exception. In this handler, you can check whether the expected exception is equal to the thrown exception and e.g. test for messages or count the occurences of the exception. By using a CountDownLatch, you can also check whether the exceptions are thrown in time and how many of them you expect.
This works even if you do not have access to the Thread created by the class under test. If you have access to it though, there is certainly an easier approach, e.g. refactoring the class under test and introduce an Exception Listener or alike. Make the class under test better testable also improves the design, e.g. by removing the dependency on Threads and directly test the body of the run() method which you could externalize.
public class ThreadExceptionTest {
private void foo() {
new Thread(new Runnable() {
#Override
public void run() {
throw new RuntimeException("exception messages");
}
}).start();
}
#Test
public void testFoo() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
final RuntimeException expectedException = new RuntimeException("exception messages");
UncaughtExceptionHandler eh = new UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
if (e.getMessage().equals(expectedException.getMessage()))
latch.countDown();
}
};
Thread.setDefaultUncaughtExceptionHandler(eh);
foo();
assertTrue(latch.await(100,TimeUnit.MILLISECONDS));
}
}
Well, unit tests are supposed to verify results of method calls, not implementation details.
In your library, if thread terminates, how does it affect library user? Maybe computations won't be finished and end results won't be recored in database? Then check database. Maybe thread will stop doing some periodic tasks (like cleanup)? Then check whether cleanup is still being done.
And if exception thrown won't affect user in any way, then there's nothing to check. Because whether exception is thrown or not is just an implementation details (user will never see it).
One option is to make the capability to start a thread a dependency - which you can specify using the existing ThreadFactory interface. Then in your unit test you can provide a specialist ThreadFactory which wraps the given Runnable in order to record exceptions etc.
You'll be able to test that:
The ThreadFactory was used
The thread was started
The operation threw an exception

Categories