4

I have an example that seems strange to me.

public class Join {
    public static void main(String[] args) {
        Thread t1 = new Thread(
                new Runnable() {
                    public void run() {
                        System.out.println(Thread.currentThread().getName());
                    }
                }
        );
        Thread t2 = new Thread(t1);
        t1.setName("t1");
        t2.setName("t2");
        t1.start();
        try {t1.join();} catch (InterruptedException ie) {}
        t2.start();
    }
}

We'll see printed only t1. If we'll comment "t1.join", we'll se the expected output (t1 t2). Why ?

Bax
  • 4,260
  • 5
  • 43
  • 65

3 Answers3

10

The second thread is created incorrectly:

Thread t2 = new Thread(t1);

I can't support it by documentation, but in the source code of Thread.run() I see:

if (target != null) {
    target.run();
}

Where target is Runnable instance. When the Thread is done, it clears the target variable:

private void exit() {
  //...
  target = null;

This means that when the first thread is done (join() method) it clears the target and the second thread does nothing. When join() is removed, both access the same target of t1 (race condition).

TL;DR

Never create a thread using another thread instance (even though it implements Runnable). Instead create a separate Runnable and pass it:

final Runnable run = new Runnable() {
    public void run() {
        System.out.println(Thread.currentThread().getName());
    }
};
Thread t1 = new Thread(run, "t1");
Thread t2 = new Thread(run, "t2");  //new Thread(t1, "t2"); is incorrect!
t1.start();
t2.start();

You don't need any join()s here, by default these are non-daemon threads.

See also

Community
  • 1
  • 1
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • Thanks a lot, I understand this is a very bad practice and of course join() here is for no reason, it was just from curiosity. – Bax Mar 21 '12 at 08:38
0

This is because main thread waits for t1 to die when you call t1.join(). And when you do this

Thread t2 = new Thread(t1);

you are passing t1 as target object whose run method is called.

Kuldeep Jain
  • 8,409
  • 8
  • 48
  • 73
0

Add before t2.start();:

System.out.println("t1 is alive: " + t1.isAlive());

If main thread is waiting for t1 to die then t2.start() can not run t1's run method. Otherwise, without waiting for t1 to die, t2 can run t1's run method.

Boris Pavlović
  • 63,078
  • 28
  • 122
  • 148