views:

73

answers:

5

Hi,

Ran into a problem. I have a spawned thread that must call its finally block. Assuming code below, is it possible to ensure that finally in the runnable is called?

import org.junit.Test;

public class ThreadTest {
    @Test
    public void testThreadFinally() throws InterruptedException {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("Going to sleep...");                    
                    Thread.sleep(1000);
                    System.out.println("slept 1000 ms");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    System.out.println("Must print this.");
                }
            }
        };
        Thread t = new Thread(r);
        t.setDaemon(false);
        t.start();
        Thread.sleep(500);
        System.out.println("main thread about to throw runtime...");
        throw new RuntimeException("fail");
    }
}
A: 

It works for me.

Jonathan Feinberg
With the update I just posted?You get "Must print this." in the console?
Tomas
what Java version if so?
Tomas
Yes, it prints the expected text, in Java 5 and Java 6.
Jonathan Feinberg
+1  A: 

As far as I can work out, the only way that finally wouldn't run is if your main thread called System.exit().

Benj
Hang on,If I run it as a Junit test I don't get the finally. I suspect Junit is doing a system.exit()....
Benj
Yes, confirmed. JUnit is calling system.exit() after it catches the runtime exception which is shutting down the JVM.
Benj
+1  A: 

If your test harness runs completely in 1000 milliseconds, you will never see the finally message, as the JVM has already shut down.

Adam Goode
+1  A: 

WFM too. But tested without jUnit in commandline. Might have something to do with that. Maybe jUnit just shuts down the VM, which runs the test, when an unexpected excpetion occurs. Did you try adding

@Test (expected=RuntimeException.class)

to the method.

Or jUnit in this case doesn't behave as if you run the same code in a main(..) { } block

Output when run in console

Going to sleep...
main thread about to throw runtime...
Exception in thread "main" java.lang.RuntimeException: fail
        at Test.main(Test.java:22)
slept 1000 ms
Must print this.
jitter
Yes, thats it, thought I had recreated another problem, but that was a dead end... thanks
Tomas
A: 

Your problem is almost certainly due to running this in JUnit, which will cause System.exit() to be called. Your Runnable, as written, is guaranteed to have its finally blocked executed before it exits. The only ways it can't exit after invoked are:

  • Infinite loop in the method itself
  • Process exits due to some thread calling System.exit() (possibly the Runnable itself).
  • Java process is forcibly terminated externally (e.g. via Unix's kill command).
Andrzej Doyle