百度了一下,终于明白了。这个解释最简单:
前提:join()方法肯定是被某个线程调用的。
A线程正在执行,突然执行的时候碰到了B.join(), 那么,A线程就必须要等到B线程执行完之后才能执行。
注意理解,是在A线程运行中,遇到了B.join().
MyTthread d = new MyThread();
Thread t1 = new Thread(d);
Thread t2 = new Thread(d);
t1.start();
t1.join();
t2.start();
这个是main线程运行的时候碰到了t1.join, 那么主线程就必须要等到t1线程执行完了之后,才能继续执行主线程。
至于,t1与t2线程,二者还是竞争关系。这个可以通过代码简单去验证:

package thread; public class ThreadTest{ public static void main(String[] args) throws InterruptedException { MyThread d1 = new MyThread("t1",2000); MyThread d2 = new MyThread("t2", 2000); Thread t1 = new Thread(d1); Thread t2 = new Thread(d2); t1.start(); t2.start(); t1.join(); for(int i = 0; i < 50; i++){ System.out.println("Main:-->" + i); } } } class MyThread extends Thread{ private String threadName; private int times; public MyThread(String threadName, int times){ this.threadName = threadName; this.times = times; } public void run(){ for(int i = 0 ; i < times; i++){ System.out.println(threadName + ":-->" + i); } } }
这个的结果,main线程执行到t1.start(), t1线程启动后继续执行,当main线程执行到t1.join()时,main线程开始等待t1执行完成,完成之后,main线程继续执行,执行到t2.start()时,t2线程才开始启动。
如果10-12行换一下顺序:
t1.start();
t2.start();
t1.join();
那么,应该是t1线程和t2线程交叉执行,当执行到t1.join()时,main线程等待t1执行完成,但是t1和t2依然是竞争关系,等t1执行完成之后,main线程会开始执行,如果t2这个时候还没有完成,则t2又会和main线程交叉执行。
这个测试呢,只需要在MyThread d1 = new MyThread("t1",2000);时,通过控制t1和t2线程的打印此时来控制存活时间就可以了。比如t1与t2都比较大,那么看看最后一段是不是t1和t2交叉执行的,或者t1在t2后执行的,这样就能说明t1.join()对于t2是没有任何影响的。
一般,如果t1线程有一些耗费时间的处理,那么t1.join()就会保证等t1执行完成之前,main线程还存活者,main就相当于一个守护线程。 可能t1的处理结果正是main线程处理时需要的。
有些人理解成,将两个线程合并成一个,也很好理解。这里将t1与主线程合并成一个线程,t1继续与t2竞争执行。t1线程则是顺序执行的。t1部分完成之后,main部分开始执行。
也可以这么理解,t1.join相对于main来说,加一一把锁,控制了t1与main线程之间的同步。