Small knowledge, big challenge! This article is participating in the creation activity of “Essential Tips for Programmers”

Author’s other platforms:

| CSDN:blog.csdn.net/qq_4115394…

| the nuggets: juejin. Cn/user / 651387…

| zhihu: www.zhihu.com/people/1024…

| GitHub:github.com/JiangXia-10…

| public no. : 1024 notes

This article is about 3,868 words and takes 10 minutes to read

1 introduction

In Java thread programming, the join() method basically asks the caller to execute the code following the join() method after completing the part of the run method.

Such as:

public class Demo08 { public static void main(String[] args) throws InterruptedException { Thread08 thread08 = new Thread08(); thread08.start(); // thread08.join(); System.out.println(" execute after child thread completes "); } } class Thread08 extends Thread{ @Override public void run() { try { int value = (int) (Math.random() * 10000); System.out.println(" need to wait "+ value +" milliseconds "); Thread.sleep(value); } catch (InterruptedException e) { e.printStackTrace(); }}}Copy the code

The result without the join method is as follows:

The run result after using the join method is as follows:

After printing the first sentence, wait 9,497 milliseconds to print the second sentence.

The join method causes thread A(child thread) to execute the tasks in the run method, while thread B(main thread) blocks indefinitely, waiting for thread A to destroy before continuing to execute the code following thread B. The join method has the effect of a thread running in a queue, similar to synchronous code running.

2 Join source code analysis

As you can see from the previous example, a JOIN has the effect of queuing threads, just like synchronization.

But the underlying join method uses the wait method.

The source code for join is as follows:

The join (long millis) method is called as follows:

If join (long millis) takes 0, the thread running the join (long millis) will wait (0). The wait method’s source code is as follows:

You can see that wait() actually performs wait(0). So the main thread keeps waiting.

Join (long Milis) can be found in the source code, this method uses synchronized keyword modification, that is, to call this method to obtain the lock of the child thread object, and then call wait, that is, first obtain the lock, release the lock, and then wait for wake up.

When the thread finishes running, notify is called by the subsystem of the thread, and the main thread wakes up!

A JOIN differs from synchroinzed: internally, a Join uses the wait method to wait, while the synchronized keyword uses the object locking mechanism as synchronization.

3 use of the join method

The join(long) method uses: the argument in the join(long) method sets the wait time. Such as:

public class Demo10 { public static void main(String[] args) throws InterruptedException { Thread t = new Thread10(); t.start(); t.join(2000); System.out.println(" main thread ends at "+ system.currentTimemillis ()); }} Class Thread10 extends Thread{@override public void run() {try {system.out.println (" child Thread starts with "+ System.currentTimeMillis()); Thread.sleep(5000); System.out.println(" child thread ends at "+ system.currentTimemillis ()); }catch (InterruptedException e){ e.printStackTrace(); }}}Copy the code

The results are as follows:

If the above code is changed to use sleep(2000), the effect of running is still 2000 milliseconds, and use join(2000) to run the effect is not the same, but they are different in the synchronization processing, the previous source analysis mentioned that the bottom of the join is to use wait, so the lock will be released, and sleep does not release the lock! So the joing(long) method also releases synchronous locks

Such as:

public class Demo11 { public static void main(String[] args) { Thread11_A thread11_a = new Thread11_A(); Thread11_B thread11_b = new Thread11_B(thread11_a); thread11_b.start(); Thread11_C thread11_c = new Thread11_C(thread11_a); thread11_c.start(); }} Class Thread11_A extends Thread{@override public void run() {try{system.out.println (" Thread11_A extends Thread{@override public void run() {try{system.out.println (" Thread11_A extends Thread{@override public void run() { "+System.currentTimeMillis()); Thread.sleep(5000); System.out.println(" thread A ends at: "+ system.currentTimemillis ()); }catch(InterruptedException e){ e.printStackTrace(); }} synchronized public void foo(){system.out.println (" "+ system.currentTimemillis ()); } } class Thread11_B extends Thread { private Thread11_A thread11_a; public Thread11_B(Thread11_A thread11_a) { this.thread11_a = thread11_a; } @Override public void run() { synchronized (thread11_a) { try { thread11_a.start(); // Thread.sleep(6000); thread11_a.join(); for (int i = 0; i < Integer.MAX_VALUE; i++) { String s = new String(); Math.random(); } }catch (InterruptedException e){ e.printStackTrace(); } } } } class Thread11_C extends Thread { private Thread11_A thread11_a; public Thread11_C(Thread11_A thread11_a) { this.thread11_a = thread11_a; } @Override public void run() { thread11_a.foo(); }}Copy the code

The results are as follows:

If join and interrupte methods encounter each other, an exception occurs, but the process does not end because ThreadA is still running. ThreadA is not interrupted but continues to execute normally. Such as:

public class Demo09 { public static void main(String[] args) throws InterruptedException { Thread09_B t = new Thread09_B(); t.start(); Thread.sleep(10); Thread t2 = new Thread09_C(t); t2.start(); } } class Thread09_A extends Thread{ @Override public void run() { for (int i = 0; i < Integer.MAX_VALUE; I++) {String s = new String(); Math.random(); } } } class Thread09_B extends Thread{ @Override public void run() { try { Thread09_A t1 = new Thread09_A(); t1.start(); t1.join(); System.out.println(" thread B terminates normally "); } catch (InterruptedException e) {system.out.println (" thread B ended abnormally "); e.printStackTrace(); } } } class Thread09_C extends Thread{ private Thread09_B t; public Thread09_C(Thread09_B t){ this.t = t; } @Override public void run() { t.interrupt(); }}Copy the code

The results are as follows:

Related recommendations:

  • Implement the producer/consumer pattern using Wait /notify

  • Communication between threads in multithreaded programming: Wait/Notify

  • Thread synchronization in multithreaded programming (part 1) : Synchronized method

  • Thread synchronization in multithreaded programming: Synchronized code blocks

  • Use of thread pools for multithreaded programming