What are the problems with join in Java multithreading?

Code one:

public static void main(String[] args) throws Exception {
    Thread thread = new Thread(() -> {
      try {
        TimeUnit.SECONDS.sleep(10);
        System.out.println("thread-0 thread exit.");
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }, "thread-0");
    thread.start();
    thread.join();
    System.out.println("main thread exit.");
  }

console (print and exit after 10s):

thread-0 thread exit.
main thread exit.

Process finished with exit code 0

Code 2:

public static void main(String[] args) throws Exception {
    Thread.currentThread().join();
    System.out.println("main thread exit.");
  }

console (waiting):

< hr >

question: the first section of code is main thread blocking on thread-0 thread. When thread-0 finishes execution, main thread also exits at the same time, so in the second section of code, the main > thread blocks on which thread, why not exit?

Mar.29,2021

main threads block themselves


In a nutshell, the function of the, join () method in Thread is that the calling thread waits for the thread to finish before it can continue to run.

public static void main(String[] args) throws InterruptedException
    {
        System.out.println("main start");

        Thread t1 = new Thread(new Worker("thread-1"));
        t1.start();
        t1.join();
        System.out.println("main end");
    }

in the above example, the main thread does not output "main end" until the T1 thread has finished running. If you do not add t1.join (), mainthread and T1 thread are parallel. With the addition of t1.join (), programs, it becomes sequential.

when we use join (), it is usually the main thread that waits for multiple other threads to finish execution before continuing execution. Multiple other threads do not need to wait for each other.

the following code does not allow other threads to execute concurrently, but sequentially.

public static void main(String[] args) throws InterruptedException
    {
        System.out.println("main start");

        Thread t1 = new Thread(new Worker("thread-1"));
        Thread t2 = new Thread(new Worker("thread-2"));
        t1.start();
        //t1t2
        t1.join();
        
        //t1t2
        t2.start();
        //t2
        t2.join();

        System.out.println("main end");
    }

so this will be the result


< H1 > explore < / H1 >
public static void main(String[] args) throws Exception {
    Thread.currentThread().join();
    System.out.println("main thread exit.");
  }

to understand the nature of the problem, let's follow the code. The thread's join method is as follows:

public final void join() throws InterruptedException {
        join(0);
    }

then follow:

public final synchronized void join(long millis)
    throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (millis == 0) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

according to the code, in fact, the join method ends up waiting for wait (0); this line of code, while the wait method is a local method.

according to wait's method definition, the following points are explained one by one:

    The
  • wait () method is defined in the object class and gets the monitor on that object when called, so it must be called on the Synchronize code block. From the point of view of the code, `InterruptedException` public final synchronized void join (long millis)
    throws InterruptedException`, so after calling the wait method, you are actually getting the monitor of the current object (according to the debug check, it is a main thread).
  • according to the definition of the wait method, it will only be woken up in the following situations, otherwise it will wait all the time:
<ul>
  
<li>Some other thread invokes the {@code notify} method for this
      object and thread <var>T</var> happens to be arbitrarily chosen as
      the thread to be awakened.
     
<li>Some other thread invokes the {@code notifyAll} method for this
      object.
      
<li>Some other thread {@linkplain Thread-sharpinterrupt() interrupts}
      thread <var>T</var>.
      
<li>The specified amount of real time has elapsed, more or less.  If
      {@code timeout} is zero, however, then real time is not taken into
      consideration and the thread simply waits until notified.
</ul>
< H1 > Summary < / H1 >

therefore, to answer your question is that the join method is essentially a call to the wait method. blocking after the wait method call (I don't think this is blocking) on the current thread (on the main thread), according to the definition of wait, do not call notify,notifyAll,interrupt and the timeout mechanism (this case is called wait (0), so this does not exist), then the thread will always be in a waiting state, so it will not quit.

Menu