4

I am trying to write my first multi-threaded program in Java. I can't understand why we require this exception handling around the for loops. When I compile without the try/catch clauses it gives an InterruptedException.

Here is the message:

Exception in thread "main" java.lang.Error: Unresolved compilation problem: 
Unhandled exception type InterruptedException

But when run with the try/catch, the sysout in the catch blocks are never displayed - implying no such exception was caught anyway!

public class SecondThread implements Runnable {
    Thread t;
    
    SecondThread() {
        t = new Thread(this, "Thread 2");
        t.start();
    }

    public void run() {
        try {
            for (int i=5; i>0; i--) {
                System.out.println("thread 2: " + i);
                Thread.sleep(1000);
            }
        }
        catch (InterruptedException e) {
            System.out.println("thread 2 interrupted");
        }
    }
}

public class MainThread {

    public static void main(String[] args) {
        new SecondThread();
    
        try {
            for (int i=5; i>0; i--) {
                System.out.println("main thread: " + i);
                Thread.sleep(2000);
            }
        }
        catch (InterruptedException e) {
            System.out.println("main thread interrupted");
        }
    }
}
Neuron
  • 5,141
  • 5
  • 38
  • 59
Sergio Gliesh
  • 329
  • 1
  • 2
  • 8
  • 4
    `When I compile without the try/catch clauses it gives an InterruptedException`: no it doesn't, it gives an error that you're not catching that checked exception - that's very different to the compiler giving you an exception. – OrangeDog Jun 02 '16 at 14:13
  • When I compile, it says this: Exception in thread "main" java.lang.Error: Unresolved compilation problem: Unhandled exception type InterruptedException at MainThread.main(MainThread.java:10) – Sergio Gliesh Jun 02 '16 at 14:20
  • @SergioGliesh: [edit] your question, don't write it in a comment. – Andy Turner Jun 02 '16 at 14:21
  • If you don't want to handle `InterruptedException` one option is to use [Guava](https://github.com/google/guava)'s [`Uninterruptibles.sleepUninterruptibly()`](https://google.github.io/guava/releases/snapshot/api/docs/com/google/common/util/concurrent/Uninterruptibles.html#sleepUninterruptibly%28long,%20java.util.concurrent.TimeUnit%29) which properly suppresses `InterruptedException`, but (as the name implies) means you can no longer interrupt the sleep, which is often not what you really want to do. – dimo414 Jun 02 '16 at 18:33

4 Answers4

8

The method Thread.sleep throws InterruptedException if it detects that the current thread has its interrupt flag set, waking up from its sleep early and allowing you to use the exception to relocate control to somewhere outside the current flow. That flag gets set only if something calls interrupt on the thread.

Since your program doesn't call interrupt on any of the threads, InterruptedException will not get thrown when you run this program. The compiler still requires you to catch the exception since it is a checked exception declared on the sleep method.

If you add a method like this to SecondThread

public void cancel() {
    t.interrupt();
}

then call cancel in the main method, like this:

public static void main(String[] args){
    SecondThread secondThread =  new SecondThread();

    try{
        for(int i=5 ; i>0 ; i--){
            System.out.println("main thread: " + i);
            Thread.sleep(2000);
            secondThread.cancel();
        }
    }
    catch(InterruptedException e){
        System.out.println("main thread interrupted");
    }
}

you'll see the println where the InterruptedException gets caught in SecondThread's run method.

Compile errors show up in eclipse under the Problems tab, in addition to getting called out in the editor by getting underlined in red, they show up as you're editing the code. When you run this program any exceptions will get written to the console, along with the program output.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276
0

InterruptedException is a checked exception and must be caught. In your code it is thrown by sleep-method. So if you do not wrap it or rethrow the compiler will halt, as it is a checked exception.

But in your example program, it will never get thrown in normal conditions as you do not interrupt. However, it is there to make sure that there is handling code for when a thread that is sleeping, waiting or is otherwise in a "zombie"-state has interrupt-flag set and thus is interrupted, either by code or by OS-level call.

So it IS in fact needed to catch, and it has valid uses.

Richard Tyregrim
  • 582
  • 2
  • 12
0

When I compile without the try/catch clauses it gives an InterruptedException.

Exceptions are thrown at runtime, not while compiling, so this cannot be true!

Probably the compile error you were getting was that Thread.sleep can throw InterruptedException, but SecondThread.run, from which Thread.sleep is called, does not declare that it can throw it. Therefore the compiler fails, because the exception can't go anywhere.

Normally there are two ways to solve this:

  • catch the exception, or
  • add a throws clause to your method.

The latter is not possible in this case, because SecondThread.run overrides from Runnable.run, which does not declare that it throws any exception. So you need to catch the exception.

If this is not the case, or you meant "When running after compiling without the try/catch clauses it gives an InterruptedException.", please include the exact error message you got. Actually, you should always do that when asking questions here.

Oebele
  • 581
  • 1
  • 4
  • 17
  • I don't even know how to identify compile-time versus runtime errors in Eclipse! This is what is says anyway: Exception in thread "main" java.lang.Error: Unresolved compilation problem: Unhandled exception type InterruptedException at MainThread.main(MainThread.java:10) – Sergio Gliesh Jun 02 '16 at 14:21
  • If it happens when you're compiling: it's a compile-time error. If it happens when the code is running: it's a runtime error. Hint: when it says "Unresolved compilation problem", it's a compile-time error. – Andy Turner Jun 02 '16 at 14:22
0

You have to handle InterruptedException in your threads because you're calling methods which throw InterruptedException, and Java is designed so you always have to handle checked exceptions. That is is "in a thread" is irrelevant.

As it says in JLS Sec 11.2:

The Java programming language requires that a program contains handlers for checked exceptions which can result from execution of a method or constructor (§8.4.6, §8.8.5).

These handlers can be in the form of try/catch (InterruptedException), or throws InterruptedException; however, you cannot use the latter because the method signature of void run() doesn't allow you to add a checked exception.

As such, you have to use try/catch.

Andy Turner
  • 137,514
  • 11
  • 162
  • 243