JAVA multithreading method JOIN detail and example code

  • 2020-06-07 04:32:58
  • OfStack

JAVA Multithreading JOIN

For Java developers, multi-threading should be a must, especially for Java products. This paper will express the knowledge of Java multithreading in a simple and profound way. In the following series, it will focus on the design idea, concrete implementation and application of Concurrent package provided by Professor Doug Lea.

How to speak in simple terms? My understanding is with a question, not a general view. So this series is mostly about problem solving, and I certainly hope readers will come up with better solutions and more questions. Due to the limited level, if there are any mistakes, please raise them and discuss them together. In short, I hope that through this series we can gain an in-depth understanding of Java multithreading to solve our actual development problems.

As a developer, I don't think it's necessary to discuss the basics of multithreading, such as what is a thread? How to create, etc., can be obtained from books and Google. This series focuses on how to dig deeper into multithreading to help us with normal development, such as how to implement thread pools. How to apply locks, etc.

(1) What is Join used for? Simple answer, sync, how do you sync? How does it work? The following will answer each question individually.
Since I came into contact with Java multithreading, 1 has been unable to understand Join. JDK put it this way:


  join
  public final void join(long millis)throws InterruptedException
  Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.

Does that make sense? Wait 1 period of time until the thread dies. My question is which thread, its own thread or the thread that called it.


package concurrentstudy;
/**
 *
 * @author vma
 */
public class JoinTest {
  public static void main(String[] args) {
    Thread t = new Thread(new RunnableImpl());
    t.start();
    try {
      t.join(1000);
      System.out.println("joinFinish");
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
   
    }
  }
}
class RunnableImpl implements Runnable {

  @Override
  public void run() {
    try {
      System.out.println("Begin sleep");
      Thread.sleep(1000);
      System.out.println("End sleep");
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

  }
}

The result is:


Begin sleep
End sleep
joinFinish

See, when the main thread calls t.join, the main thread waits for the t thread for 1000, what if the t thread Sleep 2000


 public void run() {
    try {
      System.out.println("Begin sleep");
      // Thread.sleep(1000);
      Thread.sleep(2000);
      System.out.println("End sleep");
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

  }

The result is:


Begin sleep
joinFinish
End sleep

This means that the main thread only waits for 1000 milliseconds, no matter when T ends. If it is ES56en.join (), look at the code:


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

So t. join() = t. join(0) 0JDK so A timeout of 0 means to wait forever literally means to wait forever, right?
Wait until t is over.

How does this work? Look at the JDK code:


 /**
   * Waits at most <code>millis</code> milliseconds for this thread to 
   * die. A timeout of <code>0</code> means to wait forever. 
   *
   * @param   millis  the time to wait in milliseconds.
   * @exception InterruptedException if any thread has interrupted
   *       the current thread. The <i>interrupted status</i> of the
   *       current thread is cleared when this exception is thrown.
   */
  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;
    }
  }
  }

The Join method is actually implemented via wait (tip: Object provides the method). When the main thread calls ES88en.join, the main thread gets the lock of the thread object t (wait means to get the lock) and calls wait(wait time) until the object wakes up the main thread, such as after exiting.

This means that when an main thread calls t.join, it must be able to get the lock of the wait object. If it cannot get it, it cannot get the lock of the wait object. Introduction to the above code:


/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package concurrentstudy;
/**
 *
 * @author vma
 */
public class JoinTest {
  public static void main(String[] args) {
    Thread t = new Thread(new RunnableImpl());
    new ThreadTest(t).start();
    t.start();
    try {
      t.join();
      System.out.println("joinFinish");
    } catch (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
   
    }
  }
}
class ThreadTest extends Thread {

  Thread thread;

  public ThreadTest(Thread thread) {
    this.thread = thread;
  }

  @Override
  public void run() {
    holdThreadLock();
  }

  public void holdThreadLock() {
    synchronized (thread) {
      System.out.println("getObjectLock");
      try {
        Thread.sleep(9000);

      } catch (InterruptedException ex) {
       ex.printStackTrace();
      }
      System.out.println("ReleaseObjectLock");
    }

  }
}

class RunnableImpl implements Runnable {

  @Override
  public void run() {
    try {
      System.out.println("Begin sleep");
      Thread.sleep(2000);
      System.out.println("End sleep");
    } catch (InterruptedException e) {
      e.printStackTrace();
    }


  }
}

new ThreadTest(t).start(); Instantiate the ThreadTest thread object, which in the holdThreadLock() method, via synchronized (thread), obtains the lock of the thread object t and releases it after Sleep (9000), which means that even if the main method t.join (1000), waits for 1 second, it must wait for the ThreadTest thread to release the t lock before entering the wait method, its actual wait time is 9000+1000 MS

The operation results are as follows:


getObjectLock
Begin sleep
End sleep
ReleaseObjectLock
joinFinish

Summary:

This section dives into the implementation of join and the JDK.

Thank you for reading, I hope to help you, thank you for your support to this site!


Related articles: