cancelling a future task in java [duplicate] - java

This question already has answers here:
Future task of ExecutorService not truly cancelling
(2 answers)
Closed 5 years ago.
I want to cancel a task submitted to ExecutorService thus allowing the corresponding thread to pick a new task from the queue.
Now this question have been answered many times on this forum.... like checking Thread.currentThread().interrupt() or catch (InterruptedException e). But if the flow of control spans across multiple methods then putting these checks makes the code clumsy. So if possible please suggest some elegant ways in java to achieve this functionality.
The problem that I'm facing is that future.cancel won't actually cancel the task. Instead it just sends an InterruptedException to the executing task and it's the task's responsibility to mark itself complete and release the thread.
So what I did is that I had to put the below block of code whenever an exception gets thrown anywhere in the execution which obviously doesn't look good !
if(e instanceof InterruptedException) {
throw e;
}
So, how to achieve this functionality in following code snippet:
public class MonitoringInParallelExp {
public static void main(String[] args) throws InterruptedException {
MyClass1 myClass1 = new MyClass1();
ExecutorService service = Executors.newFixedThreadPool(1);
Future<String> future1 = service.submit(myClass1);
Thread.sleep(2000);
System.out.println("calling cancel in Main");
future1.cancel(true);
System.out.println("finally called cancel in Main");
service.shutdown();
}
}
class MyClass1 implements Callable<String> {
#Override
public String call() throws Exception {
try{
MyClass2 myClass2 = new MyClass2();
myClass2.method2();
} catch (Exception e){
if(e instanceof InterruptedException) {
System.out.println("call:"+"e instanceof InterruptedException="+"true");
throw e;
}
System.out.println("Got exception in method1. " + e);
}
System.out.println("returning Myclass1.method1.exit");
return "Myclass1.method1.exit";
}
}
class MyClass2 {
public void method2() throws Exception{
try{
MyClass3 myClass3 = new MyClass3();
myClass3.method3();
} catch (Exception e){
if(e instanceof InterruptedException) {
System.out.println("method2:"+"e instanceof InterruptedException="+"true");
throw e;
}
System.out.println("Got exception in method2. " + e);
// in case the exception isn't InterruptedExceptionm, do some work here
}
}
}
class MyClass3 {
public void method3() throws Exception{
try{
Thread.sleep(10000);
} catch (Exception e){
if(e instanceof InterruptedException) {
System.out.println("method3:"+"e instanceof InterruptedException="+"true");
throw e;
}
System.out.println("Got exception in method3. " + e);
throw new MyException();
}
}
}
class MyException extends Exception {
}

It does not matter if you interrupt the Callable or not, because at that point it's already too late
try{
MyClass2 myClass2 = new MyClass2();
myClass2.method2();
} catch (Exception e){
Your call to future1.cancel(true); after Thread.sleep(2000) does not actually cancel the ongoing task (in this case your method2 call) it only means that it should have been cancelled before it started.
The docs point that out
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#cancel(boolean)
Attempts to cancel execution of this task. This attempt will fail if the task has already completed, has already been cancelled, or could not be cancelled for some other reason. If successful, and this task has not started when cancel is called, this task should never run. If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.
If you want to cancel a ongoing task you want to use a volatile boolean flag or something similiar.

Related

no null pointer exception message in console inside the thread [duplicate]

I have Java main class, in the class, I start a new thread, in the main, it waits until the thread dies. At some moment, I throw a runtime exception from the thread, but I can't catch the exception thrown from the thread in the main class.
Here is the code:
public class Test extends Thread
{
public static void main(String[] args) throws InterruptedException
{
Test t = new Test();
try
{
t.start();
t.join();
}
catch(RuntimeException e)
{
System.out.println("** RuntimeException from main");
}
System.out.println("Main stoped");
}
#Override
public void run()
{
try
{
while(true)
{
System.out.println("** Started");
sleep(2000);
throw new RuntimeException("exception from thread");
}
}
catch (RuntimeException e)
{
System.out.println("** RuntimeException from thread");
throw e;
}
catch (InterruptedException e)
{
}
}
}
Anybody knows why?
Use a Thread.UncaughtExceptionHandler.
Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread th, Throwable ex) {
System.out.println("Uncaught exception: " + ex);
}
};
Thread t = new Thread() {
#Override
public void run() {
System.out.println("Sleeping ...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Interrupted.");
}
System.out.println("Throwing exception ...");
throw new RuntimeException();
}
};
t.setUncaughtExceptionHandler(h);
t.start();
That's because exceptions are local to a thread, and your main thread doesn't actually see the run method. I suggest you read more about how threading works, but to quickly summarize: your call to start starts up a different thread, totally unrelated to your main thread. The call to join simply waits for it to be done. An exception that is thrown in a thread and never caught terminates it, which is why join returns on your main thread, but the exception itself is lost.
If you want to be aware of these uncaught exceptions you can try this:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("Caught " + e);
}
});
More information about uncaught exception handling can be found here.
This explains the state transition of threads dependening on whether an exceptions occured or not:
Source : http://www-public.imtbs-tsp.eu/~gibson/Teaching/CSC7322/L8-ExceptionsAndThreads.pdf
Most likely;
you don't need to pass the exception from one thread to another.
if you want to handle an exception, just do it in the thread which threw it.
your main thread doesn't need to wait from the background thread in this example, which actually means you don't need a background thread at all.
However, lets assume you do need to handle an exception from a child thread another. I would use an ExecutorService like this:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Void> future = executor.submit(new Callable<Void>() {
#Override
public Void call() throws Exception {
System.out.println("** Started");
Thread.sleep(2000);
throw new IllegalStateException("exception from thread");
}
});
try {
future.get(); // raises ExecutionException for any uncaught exception in child
} catch (ExecutionException e) {
System.out.println("** RuntimeException from thread ");
e.getCause().printStackTrace(System.out);
}
executor.shutdown();
System.out.println("** Main stopped");
prints
** Started
** RuntimeException from thread
java.lang.IllegalStateException: exception from thread
at Main$1.call(Main.java:11)
at Main$1.call(Main.java:6)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
** Main stopped
Please take a look at Thread.UncaughtExceptionHandler
Better (alternative) way is to use Callable and Future to get the same result...
Use Callable instead of Thread, then you can call Future#get() which throws any exception that the Callable threw.
AtomicReference is also a solution to pass the error to the main thread .Is same approach like the one of Dan Cruz .
AtomicReference<Throwable> errorReference = new AtomicReference<>();
Thread thread = new Thread() {
public void run() {
throw new RuntimeException("TEST EXCEPTION");
}
};
thread.setUncaughtExceptionHandler((th, ex) -> {
errorReference.set(ex);
});
thread.start();
thread.join();
Throwable newThreadError= errorReference.get();
if (newThreadError!= null) {
throw newThreadError;
}
The only change is that instead of creating a volatile variable you can use AtomicReference which did same thing behind the scenes.
Currently you are catching only RuntimeException, a sub class of Exception. But your application may throw other sub-classes of Exception. Catch generic Exception in addition to RuntimeException
Since many of things have been changed on Threading front, use advanced java API.
Prefer advance java.util.concurrent API for multi-threading like ExecutorService or ThreadPoolExecutor.
You can customize your ThreadPoolExecutor to handle exceptions.
Example from oracle documentation page:
Override
protected void afterExecute(Runnable r,
Throwable t)
Method invoked upon completion of execution of the given Runnable. This method is invoked by the thread that executed the task. If non-null, the Throwable is the uncaught RuntimeException or Error that caused execution to terminate abruptly.
Example code:
class ExtendedExecutor extends ThreadPoolExecutor {
// ...
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t == null && r instanceof Future<?>) {
try {
Object result = ((Future<?>) r).get();
} catch (CancellationException ce) {
t = ce;
} catch (ExecutionException ee) {
t = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // ignore/reset
}
}
if (t != null)
System.out.println(t);
}
}
Usage:
ExtendedExecutor service = new ExtendedExecutor();
I have added one constructor on top of above code as:
public ExtendedExecutor() {
super(1,5,60,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(100));
}
You can change this constructor to suit your requirement on number of threads.
ExtendedExecutor service = new ExtendedExecutor();
service.submit(<your Callable or Runnable implementation>);
Also from Java 8 you can write Dan Cruz answer as:
Thread t = new Thread(()->{
System.out.println("Sleeping ...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Interrupted.");
}
System.out.println("Throwing exception ...");
throw new RuntimeException(); });
t.setUncaughtExceptionHandler((th, ex)-> log(String.format("Exception in thread %d id: %s", th.getId(), ex)));
t.start();
I faced the same issue ... little work around (only for implementation not anonymous objects ) ... we can declare the class level exception object as null ... then initialize it inside the catch block for run method ... if there was error in run method,this variable wont be null .. we can then have null check for this particular variable and if its not null then there was exception inside the thread execution.
class TestClass implements Runnable{
private Exception ex;
#Override
public void run() {
try{
//business code
}catch(Exception e){
ex=e;
}
}
public void checkForException() throws Exception {
if (ex!= null) {
throw ex;
}
}
}
call checkForException() after join()
Did you play around with setDefaultUncaughtExceptionHandler() and the alike methods of the Thread class? From the API: "By setting the default uncaught exception handler, an application can change the way in which uncaught exceptions are handled (such as logging to a specific device, or file) for those threads that would already accept whatever "default" behavior the system provided."
You might find the answer to your problem there... good luck! :-)
If you implement Thread.UncaughtExceptionHandler in class that starts the Threads, you can set and then rethrow the exception:
public final class ThreadStarter implements Thread.UncaughtExceptionHandler{
private volatile Throwable initException;
public void doSomeInit(){
Thread t = new Thread(){
#Override
public void run() {
throw new RuntimeException("UNCAUGHT");
}
};
t.setUncaughtExceptionHandler(this);
t.start();
t.join();
if (initException != null){
throw new RuntimeException(initException);
}
}
#Override
public void uncaughtException(Thread t, Throwable e) {
initException = e;
}
}
Which causes the following output:
Exception in thread "main" java.lang.RuntimeException: java.lang.RuntimeException: UNCAUGHT
at com.gs.gss.ccsp.enrichments.ThreadStarter.doSomeInit(ThreadStarter.java:24)
at com.gs.gss.ccsp.enrichments.ThreadStarter.main(ThreadStarter.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.lang.RuntimeException: UNCAUGHT
at com.gs.gss.ccsp.enrichments.ThreadStarter$1.run(ThreadStarter.java:15)
Exception handling in Thread : By default run() method doesn’t throw any exception, so all checked exceptions inside the run method has to be caught and handled there only and for runtime exceptions we can use UncaughtExceptionHandler. UncaughtExceptionHandler is an interface provided by Java to handle exceptions in a Thread run method. So we can implement this interface and set back our implementing class back to Thread object using setUncaughtExceptionHandler() method. But this handler has to be set before we call start() on the tread.
if we don’t set uncaughtExceptionHandler then the Threads ThreadGroup acts as a handler.
public class FirstThread extends Thread {
int count = 0;
#Override
public void run() {
while (true) {
System.out.println("FirstThread doing something urgent, count : "
+ (count++));
throw new RuntimeException();
}
}
public static void main(String[] args) {
FirstThread t1 = new FirstThread();
t1.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
System.out.printf("Exception thrown by %s with id : %d",
t.getName(), t.getId());
System.out.println("\n"+e.getClass());
}
});
t1.start();
}
}
Nice explanation given at http://coder2design.com/thread-creation/#exceptions
It is almost always wrong to extend Thread. I cannot state this strongly enough.
Multithreading Rule #1: Extending Thread is wrong.*
If you implement Runnable instead you will see your expected behaviour.
public class Test implements Runnable {
public static void main(String[] args) {
Test t = new Test();
try {
new Thread(t).start();
} catch (RuntimeException e) {
System.out.println("** RuntimeException from main");
}
System.out.println("Main stoped");
}
#Override
public void run() {
try {
while (true) {
System.out.println("** Started");
Thread.sleep(2000);
throw new RuntimeException("exception from thread");
}
} catch (RuntimeException e) {
System.out.println("** RuntimeException from thread");
throw e;
} catch (InterruptedException e) {
}
}
}
produces;
Main stoped
** Started
** RuntimeException from threadException in thread "Thread-0" java.lang.RuntimeException: exception from thread
at Test.run(Test.java:23)
at java.lang.Thread.run(Thread.java:619)
* unless you want to change the way your application uses threads, which in 99.9% of cases you don't. If you think you are in the 0.1% of cases, please see rule #1.
My solution with RxJava:
#Test(expectedExceptions = TestException.class)
public void testGetNonexistentEntry() throws Exception
{
// using this to work around the limitation where the errors in onError (in subscribe method)
// cannot be thrown out to the main thread
AtomicReference<Exception> ex = new AtomicReference<>();
URI id = getRandomUri();
canonicalMedia.setId(id);
client.get(id.toString())
.subscribe(
m ->
fail("Should not be successful"),
e ->
ex.set(new TestException()));
for(int i = 0; i < 5; ++i)
{
if(ex.get() != null)
throw ex.get();
else
Thread.sleep(1000);
}
Assert.fail("Cannot find the exception to throw.");
}
For those who needs to stop all Threads running and re-run all of them when any one of them is stopped on an Exception:
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// could be any function
getStockHistory();
}
public void getStockHistory() {
// fill a list of symbol to be scrapped
List<String> symbolListNYSE = stockEntityRepository
.findByExchangeShortNameOnlySymbol(ContextRefreshExecutor.NYSE);
storeSymbolList(symbolListNYSE, ContextRefreshExecutor.NYSE);
}
private void storeSymbolList(List<String> symbolList, String exchange) {
int total = symbolList.size();
// I create a list of Thread
List<Thread> listThread = new ArrayList<Thread>();
// For each 1000 element of my scrapping ticker list I create a new Thread
for (int i = 0; i <= total; i += 1000) {
int l = i;
Thread t1 = new Thread() {
public void run() {
// just a service that store in DB my ticker list
storingService.getAndStoreStockPrice(symbolList, l, 1000,
MULTIPLE_STOCK_FILL, exchange);
}
};
Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread thread, Throwable exception) {
// stop thread if still running
thread.interrupt();
// go over every thread running and stop every one of them
listThread.stream().forEach(tread -> tread.interrupt());
// relaunch all the Thread via the main function
getStockHistory();
}
};
t1.start();
t1.setUncaughtExceptionHandler(h);
listThread.add(t1);
}
}
To sum up :
You have a main function that create multiple thread, each of them has UncaughtExceptionHandler which is trigger by any Exception inside of a thread. You add every Thread to a List. If a UncaughtExceptionHandler is trigger it will loop through the List, stop every Thread and relaunch the main function recreation all the Thread.
You cannot do this, since it doesn't really make sense. If you hadn't called t.join() then you main thread could be anywhere in the code when the t thread throws an exception.

ThreadPoolExecutor - differences between submit and execute methods? [duplicate]

This question already has answers here:
Choose between ExecutorService's submit and ExecutorService's execute
(7 answers)
Closed 9 years ago.
I faced a problem about ThreadPoolExecutor.
After writing some code, I found the submit() method will eat the RuntimeException thrown by the program, but the execute() method will re-throw the RuntimeException`. I want to know the reason for this.
I recently read the source code of ThreadPoolExecutor and know the principle of a thread pool.
Now I understand how execute() method executes, but I couldn't understand how submit() method executes. I only know that the submit() method will wrap the Runnable or Callable in a FutureTask and call the execute() method:
public Future submit(Runnable runnable)
{
if(runnable == null)
{
throw new NullPointerException();
} else
{
RunnableFuture runnablefuture = newTaskFor(runnable, null);
execute(runnablefuture);
return runnablefuture;
}
}
So, my problem is: how does ThreadPoolExecutor execute FutureTask and why is the RuntimeException eaten?
If you look into newTaskFor method you'll see that RunnableFuture is in fact instance of java.util.concurrent.FutureTask. You should see the run method in this FutureTask class.
public void run() {
sync.innerRun();
}
and here is the innerRun method:
void innerRun() {
if (!compareAndSetState(READY, RUNNING))
return;
runner = Thread.currentThread();
if (getState() == RUNNING) { // recheck after setting thread
V result;
try {
result = callable.call();
} catch (Throwable ex) {
setException(ex);
return;
}
set(result);
} else {
releaseShared(0); // cancel
}
}
the exception is caught and set to task. It will be thrown wrapped into ExecutionException when you call get method of FutureTask
public V get() throws InterruptedException, ExecutionException {
return sync.innerGet();
}

Can nested threads throw exceptions for parent thread?

I have a Controller class and a Monitor worker thread.
The controller thread looks something like this
public class ControllerA {
public void ControllerA(){
try{
doWork();
}
catch(OhNoException e){
//catch exception
}
public void doWork() throws OhNoException{
new Thread(new Runnable(){
public void run(){
//Needs to monitor resources of ControllerA,
//if things go wrong, it needs to throw OhNoException for its parent
}
}).start();
//do work here
}
}
Is such setup feasible? How do I throw exception to the outside of the thread?
How do I throw exception to the outside of the thread?
Couple ways you can do this. You can set a UncaughtExceptionHandler on the thread or you can use an ExecutorService.submit(Callable) and use the exception that you get from the Future.get().
The easiest way is to use the ExecutorService:
ExecutorService threadPool = Executors.newSingleThreadScheduledExecutor();
Future<Void> future = threadPool.submit(new Callable<Void>() {
public Void call() throws Exception {
// can throw OhNoException here
return null;
}
});
// you need to shut down the pool after submitting the last task
threadPool.shutdown();
try {
// this waits for your background task to finish, it throws if the task threw
future.get();
} catch (ExecutionException e) {
// this is the exception thrown by the call() which could be a OhNoException
Throwable cause = e.getCause();
if (cause instanceof OhNoException) {
throw (OhNoException)cause;
} else if (cause instanceof RuntimeException) {
throw (RuntimeException)cause;
}
}
If you want to use the UncaughtExceptionHandler then you can do something like:
Thread thread = new Thread(...);
final AtomicReference throwableReference = new AtomicReference<Throwable>();
thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
throwableReference.set(e);
}
});
thread.start();
thread.join();
Throwable throwable = throwableReference.get();
if (throwable != null) {
if (throwable instanceof OhNoException) {
throw (OhNoException)throwable;
} else if (throwable instanceof RuntimeException) {
throw (RuntimeException)throwable;
}
}
Runnable interface cannot throw checked exceptions or return values. In The Callable interface you can call any worker method that return values or throws exceptions. The main tasks of the monitor would be
To declare and initialize the future with the callable instance.
A getResult() method that can have a return future.get(); statement and should declare any checked exceptions in its throws clause for it to be handled by the calling code. In this way we dont have to return a null.

Spring Aspect fails when join point is invoked in new thread

I'm using Spring 3.0.5 with an Around aspect.
The #Around aspect works perfectly. The AOP expression targets the interfaces of a bunch of beans.
The aspect executes some logic before and after the invokation:
#Around(...)
public Object monitor(ProceedingJoinPoint pjp) throws Throwable {
// some code
Obj o = pjp.proceed();
// some code
}
No big deal.
Now, I'm trying to create another aspect that throws an exception if the intercepted method takes too long.
private static ExecutorService executor = Executors.newCachedThreadPool();
#Around(...)
public Object monitor(ProceedingJoinPoint pjp) throws Throwable {
Object obj = null;
Callable<Object> task = new Callable<Object>() {
public Object call() {
return pjp.proceed();
}
};
Future<Object> future = executor.submit(task);
try {
obj = future.get(timeout, TimeUnit.MILLISECONDS);
} catch (TimeoutException ex) {
...
} catch (InterruptedException e) {
// we ignore this one...
} catch (ExecutionException e) {
throw e.getCause(); // rethrow any exception raised by the invoked method
} finally {
future.cancel(true); // may or may not desire this
}
return obj;
}
When I execute the code with only this aspect applied I get the following exception:
java.lang.RuntimeException: java.lang.IllegalStateException: No
MethodInvocation found: Check that an AOP invocation is in progress,
and that the ExposeInvocationInterceptor is in the interceptor chain.
From the Spring documentation I read:
"Class ExposeInvocationInterceptor
Interceptor that exposes the current MethodInvocation as a thread-local object."
So it looks like that the target got lost because I basically start a new thread and the new thread doesn't have access to thread local. Is there a way to solve this problem or a better approach?
Thanks
The solution was quite trivial. The Aspect that checks how long a method takes must be the last in the "chain" of aspects. I have used the #Order annotation on the Aspect to make it the last one to be executed.
That did the trick.
If the Aspect is not the last to be executed, the new Thread is not able to access the ThreadLocal variable containing the ExposeInvocationInterceptor class.
You could try interrupting the current thread from another thread, if the pjp.proceed() call is amenable to interruption. E.g. your aspect looks like:
new Interrupter(Thread.currentThread()).start();
// Following call will get interrupted if it takes too long
try {
return pjp.proceed();
} catch (InterruptedException ex) {
// do something?
}
where the Interrupter class would be something like:
static class Interrupter extends Thread {
private final Thread other;
Interrupter(final Thread other) {
this.other = other;
}
#Override
public void run() {
try {
Thread.sleep(500); // or whatever your timeout is
} catch (final InterruptedException e) {
e.printStackTrace();
}
if (other.isAlive()) {
other.interrupt();
}
}
}

How to catch an Exception from a thread

I have Java main class, in the class, I start a new thread, in the main, it waits until the thread dies. At some moment, I throw a runtime exception from the thread, but I can't catch the exception thrown from the thread in the main class.
Here is the code:
public class Test extends Thread
{
public static void main(String[] args) throws InterruptedException
{
Test t = new Test();
try
{
t.start();
t.join();
}
catch(RuntimeException e)
{
System.out.println("** RuntimeException from main");
}
System.out.println("Main stoped");
}
#Override
public void run()
{
try
{
while(true)
{
System.out.println("** Started");
sleep(2000);
throw new RuntimeException("exception from thread");
}
}
catch (RuntimeException e)
{
System.out.println("** RuntimeException from thread");
throw e;
}
catch (InterruptedException e)
{
}
}
}
Anybody knows why?
Use a Thread.UncaughtExceptionHandler.
Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread th, Throwable ex) {
System.out.println("Uncaught exception: " + ex);
}
};
Thread t = new Thread() {
#Override
public void run() {
System.out.println("Sleeping ...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Interrupted.");
}
System.out.println("Throwing exception ...");
throw new RuntimeException();
}
};
t.setUncaughtExceptionHandler(h);
t.start();
That's because exceptions are local to a thread, and your main thread doesn't actually see the run method. I suggest you read more about how threading works, but to quickly summarize: your call to start starts up a different thread, totally unrelated to your main thread. The call to join simply waits for it to be done. An exception that is thrown in a thread and never caught terminates it, which is why join returns on your main thread, but the exception itself is lost.
If you want to be aware of these uncaught exceptions you can try this:
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
#Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("Caught " + e);
}
});
More information about uncaught exception handling can be found here.
This explains the state transition of threads dependening on whether an exceptions occured or not:
Source : http://www-public.imtbs-tsp.eu/~gibson/Teaching/CSC7322/L8-ExceptionsAndThreads.pdf
Most likely;
you don't need to pass the exception from one thread to another.
if you want to handle an exception, just do it in the thread which threw it.
your main thread doesn't need to wait from the background thread in this example, which actually means you don't need a background thread at all.
However, lets assume you do need to handle an exception from a child thread another. I would use an ExecutorService like this:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Void> future = executor.submit(new Callable<Void>() {
#Override
public Void call() throws Exception {
System.out.println("** Started");
Thread.sleep(2000);
throw new IllegalStateException("exception from thread");
}
});
try {
future.get(); // raises ExecutionException for any uncaught exception in child
} catch (ExecutionException e) {
System.out.println("** RuntimeException from thread ");
e.getCause().printStackTrace(System.out);
}
executor.shutdown();
System.out.println("** Main stopped");
prints
** Started
** RuntimeException from thread
java.lang.IllegalStateException: exception from thread
at Main$1.call(Main.java:11)
at Main$1.call(Main.java:6)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:662)
** Main stopped
Please take a look at Thread.UncaughtExceptionHandler
Better (alternative) way is to use Callable and Future to get the same result...
Use Callable instead of Thread, then you can call Future#get() which throws any exception that the Callable threw.
AtomicReference is also a solution to pass the error to the main thread .Is same approach like the one of Dan Cruz .
AtomicReference<Throwable> errorReference = new AtomicReference<>();
Thread thread = new Thread() {
public void run() {
throw new RuntimeException("TEST EXCEPTION");
}
};
thread.setUncaughtExceptionHandler((th, ex) -> {
errorReference.set(ex);
});
thread.start();
thread.join();
Throwable newThreadError= errorReference.get();
if (newThreadError!= null) {
throw newThreadError;
}
The only change is that instead of creating a volatile variable you can use AtomicReference which did same thing behind the scenes.
Currently you are catching only RuntimeException, a sub class of Exception. But your application may throw other sub-classes of Exception. Catch generic Exception in addition to RuntimeException
Since many of things have been changed on Threading front, use advanced java API.
Prefer advance java.util.concurrent API for multi-threading like ExecutorService or ThreadPoolExecutor.
You can customize your ThreadPoolExecutor to handle exceptions.
Example from oracle documentation page:
Override
protected void afterExecute(Runnable r,
Throwable t)
Method invoked upon completion of execution of the given Runnable. This method is invoked by the thread that executed the task. If non-null, the Throwable is the uncaught RuntimeException or Error that caused execution to terminate abruptly.
Example code:
class ExtendedExecutor extends ThreadPoolExecutor {
// ...
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (t == null && r instanceof Future<?>) {
try {
Object result = ((Future<?>) r).get();
} catch (CancellationException ce) {
t = ce;
} catch (ExecutionException ee) {
t = ee.getCause();
} catch (InterruptedException ie) {
Thread.currentThread().interrupt(); // ignore/reset
}
}
if (t != null)
System.out.println(t);
}
}
Usage:
ExtendedExecutor service = new ExtendedExecutor();
I have added one constructor on top of above code as:
public ExtendedExecutor() {
super(1,5,60,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(100));
}
You can change this constructor to suit your requirement on number of threads.
ExtendedExecutor service = new ExtendedExecutor();
service.submit(<your Callable or Runnable implementation>);
Also from Java 8 you can write Dan Cruz answer as:
Thread t = new Thread(()->{
System.out.println("Sleeping ...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("Interrupted.");
}
System.out.println("Throwing exception ...");
throw new RuntimeException(); });
t.setUncaughtExceptionHandler((th, ex)-> log(String.format("Exception in thread %d id: %s", th.getId(), ex)));
t.start();
I faced the same issue ... little work around (only for implementation not anonymous objects ) ... we can declare the class level exception object as null ... then initialize it inside the catch block for run method ... if there was error in run method,this variable wont be null .. we can then have null check for this particular variable and if its not null then there was exception inside the thread execution.
class TestClass implements Runnable{
private Exception ex;
#Override
public void run() {
try{
//business code
}catch(Exception e){
ex=e;
}
}
public void checkForException() throws Exception {
if (ex!= null) {
throw ex;
}
}
}
call checkForException() after join()
Did you play around with setDefaultUncaughtExceptionHandler() and the alike methods of the Thread class? From the API: "By setting the default uncaught exception handler, an application can change the way in which uncaught exceptions are handled (such as logging to a specific device, or file) for those threads that would already accept whatever "default" behavior the system provided."
You might find the answer to your problem there... good luck! :-)
If you implement Thread.UncaughtExceptionHandler in class that starts the Threads, you can set and then rethrow the exception:
public final class ThreadStarter implements Thread.UncaughtExceptionHandler{
private volatile Throwable initException;
public void doSomeInit(){
Thread t = new Thread(){
#Override
public void run() {
throw new RuntimeException("UNCAUGHT");
}
};
t.setUncaughtExceptionHandler(this);
t.start();
t.join();
if (initException != null){
throw new RuntimeException(initException);
}
}
#Override
public void uncaughtException(Thread t, Throwable e) {
initException = e;
}
}
Which causes the following output:
Exception in thread "main" java.lang.RuntimeException: java.lang.RuntimeException: UNCAUGHT
at com.gs.gss.ccsp.enrichments.ThreadStarter.doSomeInit(ThreadStarter.java:24)
at com.gs.gss.ccsp.enrichments.ThreadStarter.main(ThreadStarter.java:38)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
Caused by: java.lang.RuntimeException: UNCAUGHT
at com.gs.gss.ccsp.enrichments.ThreadStarter$1.run(ThreadStarter.java:15)
Exception handling in Thread : By default run() method doesn’t throw any exception, so all checked exceptions inside the run method has to be caught and handled there only and for runtime exceptions we can use UncaughtExceptionHandler. UncaughtExceptionHandler is an interface provided by Java to handle exceptions in a Thread run method. So we can implement this interface and set back our implementing class back to Thread object using setUncaughtExceptionHandler() method. But this handler has to be set before we call start() on the tread.
if we don’t set uncaughtExceptionHandler then the Threads ThreadGroup acts as a handler.
public class FirstThread extends Thread {
int count = 0;
#Override
public void run() {
while (true) {
System.out.println("FirstThread doing something urgent, count : "
+ (count++));
throw new RuntimeException();
}
}
public static void main(String[] args) {
FirstThread t1 = new FirstThread();
t1.setUncaughtExceptionHandler(new UncaughtExceptionHandler() {
public void uncaughtException(Thread t, Throwable e) {
System.out.printf("Exception thrown by %s with id : %d",
t.getName(), t.getId());
System.out.println("\n"+e.getClass());
}
});
t1.start();
}
}
Nice explanation given at http://coder2design.com/thread-creation/#exceptions
It is almost always wrong to extend Thread. I cannot state this strongly enough.
Multithreading Rule #1: Extending Thread is wrong.*
If you implement Runnable instead you will see your expected behaviour.
public class Test implements Runnable {
public static void main(String[] args) {
Test t = new Test();
try {
new Thread(t).start();
} catch (RuntimeException e) {
System.out.println("** RuntimeException from main");
}
System.out.println("Main stoped");
}
#Override
public void run() {
try {
while (true) {
System.out.println("** Started");
Thread.sleep(2000);
throw new RuntimeException("exception from thread");
}
} catch (RuntimeException e) {
System.out.println("** RuntimeException from thread");
throw e;
} catch (InterruptedException e) {
}
}
}
produces;
Main stoped
** Started
** RuntimeException from threadException in thread "Thread-0" java.lang.RuntimeException: exception from thread
at Test.run(Test.java:23)
at java.lang.Thread.run(Thread.java:619)
* unless you want to change the way your application uses threads, which in 99.9% of cases you don't. If you think you are in the 0.1% of cases, please see rule #1.
My solution with RxJava:
#Test(expectedExceptions = TestException.class)
public void testGetNonexistentEntry() throws Exception
{
// using this to work around the limitation where the errors in onError (in subscribe method)
// cannot be thrown out to the main thread
AtomicReference<Exception> ex = new AtomicReference<>();
URI id = getRandomUri();
canonicalMedia.setId(id);
client.get(id.toString())
.subscribe(
m ->
fail("Should not be successful"),
e ->
ex.set(new TestException()));
for(int i = 0; i < 5; ++i)
{
if(ex.get() != null)
throw ex.get();
else
Thread.sleep(1000);
}
Assert.fail("Cannot find the exception to throw.");
}
For those who needs to stop all Threads running and re-run all of them when any one of them is stopped on an Exception:
#Override
public void onApplicationEvent(ContextRefreshedEvent event) {
// could be any function
getStockHistory();
}
public void getStockHistory() {
// fill a list of symbol to be scrapped
List<String> symbolListNYSE = stockEntityRepository
.findByExchangeShortNameOnlySymbol(ContextRefreshExecutor.NYSE);
storeSymbolList(symbolListNYSE, ContextRefreshExecutor.NYSE);
}
private void storeSymbolList(List<String> symbolList, String exchange) {
int total = symbolList.size();
// I create a list of Thread
List<Thread> listThread = new ArrayList<Thread>();
// For each 1000 element of my scrapping ticker list I create a new Thread
for (int i = 0; i <= total; i += 1000) {
int l = i;
Thread t1 = new Thread() {
public void run() {
// just a service that store in DB my ticker list
storingService.getAndStoreStockPrice(symbolList, l, 1000,
MULTIPLE_STOCK_FILL, exchange);
}
};
Thread.UncaughtExceptionHandler h = new Thread.UncaughtExceptionHandler() {
public void uncaughtException(Thread thread, Throwable exception) {
// stop thread if still running
thread.interrupt();
// go over every thread running and stop every one of them
listThread.stream().forEach(tread -> tread.interrupt());
// relaunch all the Thread via the main function
getStockHistory();
}
};
t1.start();
t1.setUncaughtExceptionHandler(h);
listThread.add(t1);
}
}
To sum up :
You have a main function that create multiple thread, each of them has UncaughtExceptionHandler which is trigger by any Exception inside of a thread. You add every Thread to a List. If a UncaughtExceptionHandler is trigger it will loop through the List, stop every Thread and relaunch the main function recreation all the Thread.
You cannot do this, since it doesn't really make sense. If you hadn't called t.join() then you main thread could be anywhere in the code when the t thread throws an exception.

Categories