百度了一下,终于明白了。这个解释最简单:
前提: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线程之间的同步。