Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ?

like image 501
Bax Avatar asked Dec 27 '22 03:12

Bax


1 Answers

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

  • Java Threading Basics (discussion on #2)
like image 120
Tomasz Nurkiewicz Avatar answered Jan 14 '23 01:01

Tomasz Nurkiewicz