join()方法用来挂起当前运行状态的线程,直到定义的线程执行完毕。在很多情况下,主线程创建并启动子线程,如果子线程中要进行大量的耗时运算,主线程将可能早于子线程结束。如果主线程需要知道子线程的执行结果时,就需要等待子线程执行结束了。主线程可以sleep(xx),但这样的xx时间不好确定,因为子线程的执行时间不确定,​​join()​​方法比较合适这个场景。这个常见的一个应用就是安装程序,很多大的软件都会包含多个插件,如果选择完整安装,则要等所有的插件都安装完成才能结束,且插件与插件之间还可能会有依赖关系。

Java join线程合并、排队、插队_主线程

安装插件

public class PluginTest {
public static void main(String[] args) {
System.out.println("主线程开启...");
Thread thread1 = new Thread(new Plugin1());
Thread thread2 = new Thread(new Plugin2());
try {
thread1.start(); //开始插件1的安装
thread1.join(); //等插件1的安装线程结束
thread2.start(); //再开始插件2的安装
thread2.join(); //等插件2的安装线程结束,才能回到主线程
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("主线程结束,程序安装完成!");
}
}
/**
* 插件1
*/
class Plugin1 implements Runnable {

@Override
public void run() {
System.out.println("插件1开始安装.");
System.out.println("安装中...");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("插件1完成安装.");
}
}

/**
* 插件2
*/
class Plugin2 implements Runnable {

@Override
public void run() {
System.out.println("插件2开始安装.");
System.out.println("安装中...");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("插件2完成安装.");
}
}

Java join线程合并、排队、插队_主线程_02

join指定顺序执行

未加入join时,线程执行顺序是混乱的

public class JoinExample2 {
public static void main(String[] args) {
Thread th1 = new Thread(new MyClass2(), "th1");
Thread th2 = new Thread(new MyClass2(), "th2");
Thread th3 = new Thread(new MyClass2(), "th3");

th1.start();
th2.start();
th3.start();
}
}

class MyClass2 implements Runnable{

@Override
public void run() {
Thread t = Thread.currentThread();
System.out.println("Thread started: "+t.getName());
try {
Thread.sleep(4000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
System.out.println("Thread ended: "+t.getName());
}
}

Java join线程合并、排队、插队_ide_03

加入join后,线程按照指定的顺序执行

public class JoinExample {
public static void main(String[] args) {
Thread th1 = new Thread(new MyClass(), "th1");
Thread th2 = new Thread(new MyClass(), "th2");
Thread th3 = new Thread(new MyClass(), "th3");

// 立刻开启第一个线程
th1.start();

/*
* 当第一个线程执行完毕,开启第二个线程
*/
try {
th1.join();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
th2.start();

/*
* 当第二个线程完毕,开启第三个线程
*/
try {
th2.join();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
th3.start();

// 当第三个线程执行完毕,显示一条消息
try {
th3.join();
} catch (InterruptedException ie) {
ie.printStackTrace();
}
System.out.println("All three threads have finished execution");
}
}

class MyClass implements Runnable{

@Override
public void run() {
Thread t = Thread.currentThread();
System.out.println("Thread started: "+t.getName());
try {
Thread.sleep(4000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
System.out.println("Thread ended: "+t.getName());

}
}

Java join线程合并、排队、插队_子线程_04