views:

133

answers:

3

Please help me understand this program's execution and what concepts apply here in the larger sense? An illustration which explains thread(s)/stack(s) creations and destruction would be helpful.

class Joining {

    static Thread createThread(final int i, final Thread t1) {
        Thread t2 = new Thread() {
            public void run() {
                System.out.println(i+1);
                try {
                    t1.join(); 
                } catch (InterruptedException ie) {
                }
                System.out.println(i+2);
            }
        };
        System.out.println(i+3);
        t2.start(); //1
        System.out.println(i+4);
        return t2;
    }
    public static void main(String[] args) {
        createThread(10, createThread(20, Thread.currentThread()));
    }
}
A: 

Hmm...seems to me like the t1.join will hang forever on the first createThread(20, Thread.currentThread)) call.

Gandalf
...until the main thread terminates. Then the "20" thread will terminate, allowing for the "10" thread to join the "20" thread and then terminates. In shorts: t20 waits for main to terminate, t10 waits for t20 to terminates, main terminates, so t20 terminates so t10 terminates.
gawi
+4  A: 
  1. The inner createThread call is called at the bottom from the main thread [M], with the arguments 20 and the current thread.
  2. This call prints 23.
  3. A new thread [A] is started (and will be returned) which prints 21, and waits for the main thread [M] to die (and will print 22 after it does).
  4. This call prints 24. It's impossible to know if this will happen before the new thread [A] prints 21.
  5. This call returns the new thread [A], which is waiting for the main thread [M] to die.
  6. The new thread [A] is passed as the second argument to the createThread call with 10 as the first argument.
  7. This call prints 13.
  8. Another new thread [B] is started (and will be returned although nobody is catching this return) which prints 11, and waits for the first created thread [A] to die (and will print 12 after it does).
  9. This call prints 14. It's impossible to know if this will happen before this second new thread [B] prints 11.
  10. This call returns the second new thread [B], which is waiting for the first created thread [A] to die, but nothing is being done with this return call.
  11. The main thread [M] runs out of things to do and dies.
  12. When the main thread [M] dies, the join() call on the first created thread [A] returns.
  13. The first created thread [A] prints 22.
  14. The first created thread [A] dies.
  15. When the first created thread [A] dies, the join() call on the second created thread [B] returns.
  16. The second created thread [B] prints 12.
  17. The second created thread [B] dies.
  18. The JVM shuts down, because all threads have died.
Erick Robertson
after starting a thread at (3.) i.e t2.start() why will it always execute the next line to print 24 at (4.). Because once you start a thread isn't it possible that instead of printing 24 the run() of t2 will start executing and print 21 before 24. I am asking why is 24 consistently the output here because we dont know how jvm is working here.
When `t2.start()` executes, the thread is started and the call returns immediately. The thread calling `t2.start()` immediately goes on to execute the next line. The only unknown thing is how long will the JVM take to start up this thread? That's why I don't know whether 21 or 24 will print first. They will both print at about the same time, though.
Erick Robertson
The new thread, before it calls `join()`, will be executing in parallel to the old thread which started it. Both threads will be going and will be sharing CPU cycles. In a multi-threaded CPU or a multi-core CPU or a multi-CPU machine, these threads can actually be executed at the same time.
Erick Robertson
+1  A: 

Adding some debug-output will probably help you understand the execution:

import static java.lang.Thread.currentThread;

class Joining {

    static int count = 0;

    static Thread createThread(final int i, final Thread t1) {
        System.out.println("Create thread with " + i + " and " + t1.getName());
        Thread t2 = new Thread("Thread " + count++) {
            public void run() {
                System.out.println(currentThread().getName() + ": " + (i+1));
                try {
                    System.out.println(currentThread().getName() + ": join with " + t1.getName());
                    t1.join(); 
                } catch (InterruptedException ie) {
                }
                System.out.println(currentThread().getName() + ": " + (i+2));
            }
        };
        System.out.println(currentThread().getName() + ": " + (i+3));
        System.out.println(currentThread().getName() + ": starting thread " + t2.getName());
        t2.start(); //1
        System.out.println(currentThread().getName() + ": " + (i+4));
        return t2;
    }

    public static void main(String[] args) throws InterruptedException {
        Thread someThread = createThread(20, currentThread());
        System.out.println("After first createThread.");
        Thread.sleep(1000);
        createThread(10, someThread);
    }
}

The output is

Create thread with 20 and main
main: 23
main: starting thread Thread 0
main: 24
After first createThread.
Thread 0: 21
Thread 0: join with main
Create thread with 10 and Thread 0
main: 13
main: starting thread Thread 1
main: 14
Thread 1: 11
Thread 1: join with Thread 0
Thread 0: 22
Thread 1: 12
aioobe