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?


java multithreading
Share
Follow
edited Mar 16 "15 at 15:37
*

Ciro Santilli 新疆再教育营六四事件法轮功郝海东
278k7777 gold badges10281028 silver badges831831 bronze badges
asked Jul 1 "11 at 9:37
*

NARUNARU
2,45955 gold badges2121 silver badges2828 bronze badges
0
Add a comment |

17 Answers 17


Active Oldest Votes
244
Use a Thread.UncaughtExceptionHandler.

You are watching: Exception in thread "main" java.util.inputmismatchexception

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();
Share
Follow
edited Jul 1 "20 at 23:04

*

torno
4361111 silver badges2424 bronze badges
answered Jul 1 "11 at 12:52
*

Dan CruzDan Cruz
14.5k66 gold badges3939 silver badges6464 bronze badges
3
Add a comment |
50
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.


Share
Follow
edited Jul 15 "19 at 9:09
*

Bludwarf
55255 silver badges1818 bronze badges
answered Jul 1 "11 at 9:41
abyxabyx
63.5k1616 gold badges8888 silver badges113113 bronze badges
1
Add a comment |
39
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


Share
Follow
edited Feb 18 "20 at 16:34
intvprep
7177 bronze badges
answered Jul 1 "11 at 9:45
Talha Ahmed KhanTalha Ahmed Khan
14.1k1010 gold badges4040 silver badges4848 bronze badges
1
Add a comment |
29
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 future = executor.submit(new Callable()
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
Share
Follow
edited Oct 28 "15 at 17:19
rogerdpack
53.6k3131 gold badges227227 silver badges346346 bronze badges
answered Jul 1 "11 at 10:32
Peter LawreyPeter Lawrey
506k7373 gold badges716716 silver badges10921092 bronze badges
2
Add a comment |
8
Please take a look at Thread.UncaughtExceptionHandler

Better (alternative) way is to use Callable and Future to get the same result...


Share
Follow
edited Jul 21 "16 at 14:43
Ravindra babu
44.3k88 gold badges221221 silver badges200200 bronze badges
answered Jul 1 "11 at 9:43
denis.solonenkodenis.solonenko
11.3k22 gold badges2626 silver badges2323 bronze badges
Add a comment |
5
Use Callable instead of Thread, then you can call Future#get() which throws any exception that the Callable threw.


Share
Follow
answered Jul 1 "11 at 9:41
artbristolartbristol
31k55 gold badges6464 silver badges9898 bronze badges
1
Add a comment |
3
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.

See more: Sinéad O Connor This Is A Rebel Song Lyrics, Sinead O'Connor

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(100)); You can change this constructor to suit your requirement on number of threads.