1

I am fairly new to Java threads, Runnable, and the like. As such, I'm wondering why the following code does not catch an exception?

Runnable r = () -> {
    try {
        job.print(); 
    } catch (Exception e) {
        e.printStackTrace();
    }
};

if (job.printDialog()) {
    Thread t = new Thread(r);
    r.start();
}

Reading Is there a way to make Runnable's run() throw an exception I gather that:

  1. "... if your run() method is really the target of a Thread, there's no point in throwing an exception because it is unobservable; throwing an exception has the same effect as not throwing an exception (none)." (@erickson)
  2. I should check for exceptions inside the Runnable.run() method.

Why is that? Any "simple" explanations on this matter are highly appreciated!

yulai
  • 741
  • 3
  • 20
  • 36
  • Re, "I should check for exceptions inside run()... Why is that?" Why not? If you want to write a top-level handler for exceptions thrown within the thread, where would you prefer to put it? Why _not_ use the already exising `try...catch...` mechanism in the thread's top-level function? – Solomon Slow Sep 11 '19 at 14:01

2 Answers2

1

As you have found out already, there's nothing thats captured outside Runnable running state. Language specifications keep on changing. What might have an explanation today may have something else tomorrow. You might find the answer at Why cannot run() of Runnable throw checked Exceptions?, specifically as to why Callable was added to capture the results from Future.

xploreraj
  • 3,792
  • 12
  • 33
  • 51
0

You can answer this question from both, a logical and a programmatical point of view. Let's start with the logical one:

You can think of a thread as an "independent executor of code" which is totally independent from other executors of code, except shared memory. The Runnable you have to pass on thread initialization "wraps" the code the thread has to execute. As there's no "higher instance" which could catch an exception, throwing exceptions inside those Runnables doesn't make a lot of sense.

Now the programmatical point of view. The following code snippet is similar to how the interface is defined inside the Java SE:

@FunctionalInterface
interface Runnable {
    void run();
}

As the function #run() does NOT throw any checked exceptions, you're not allowed to throw checked exceptions inside #run(). Since Runnables have been designed for use in thread initialization only, this makes perfect sense. Callables, however, contain a throws-clause as they're mainly used in Executors which indeed are able to handle exceptions.

Quaffel
  • 1,463
  • 9
  • 19