Bax
Bax

Reputation: 4476

Java join() method

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 ?

Upvotes: 4

Views: 712

Answers (3)

Kuldeep Jain
Kuldeep Jain

Reputation: 8598

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.

Upvotes: 0

Tomasz Nurkiewicz
Tomasz Nurkiewicz

Reputation: 340733

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

Upvotes: 10

Boris Pavlović
Boris Pavlović

Reputation: 64632

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.

Upvotes: 0

Related Questions