多线程Thread中的join()方法
我们都知道,join()
方法是在线程A中加入线程B,A阻塞等待B运行完,但是如果在A中一次调用多个join、加入多个子线程会不会就变成了(顺序执行)单线程的模式了。那我们来看一下join方法的具体分析吧。
这是API中对join()
方法的说明,这个说明简短的见了鬼一样,看的不懂
这是源码的注释
Waits at most millis milliseconds for this thread to die. A timeout of 0 means to wait forever.
This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
百度翻译过来是
等待此线程死亡的时间最多为毫秒。超时0表示永远等待。
此实现使用This.wait调用的循环,该循环以This.isAlive为条件。当线程终止时,调用this.notifyAll方法。建议应用程序不要在线程实例上使用wait、notify或notifyAll。
翻译的有些不准,英语不好的凑合看啊。他的 超时0表示永远等待 ,其实意思是join(long millis)
这个方法,传了一个毫秒数进去,传0的话就一直等,直到子线程死掉。
我们接下来看具体实现:
public class Test01 {
public static void main(String[] args) throws InterruptedException {
MyThreadDemo t1 = new MyThreadDemo("线程1111");
MyThreadDemo t2 = new MyThreadDemo("线程2222222222");
MyThreadDemo t3 = new MyThreadDemo("线程333");
MyThreadDemo t4 = new MyThreadDemo("线程4");
//4个线程启动,4个线程开始抢资源
t1.start();
t2.start();
t3.start();
t4.start();
//这里会导致主线程main阻塞,直到t1执行完继续往下走
//t1、t2并不是顺序执行
//这里并不是说就只有t1、t2抢资源,t3、t4一样会抢资源
t1.join();
//t1执行完,主线程main进入就绪状态,开始抢资源,继续往下走
//将t2加入,如果没有执行完的话
//main阻塞
t2.join();
//t2执行完,主线程main进入就绪状态,开始抢资源
//这一句必定会在t1和t2执行完之后才执行
//会和还未执行完的t3、t4抢资源,
// (也有可能t3、t4在t1、t2执行完之前就执行完了,就不存在抢资源了,只剩下main一个前台线程
//注:垃圾回收器是后台线程(守护线程),只要还有线程在,垃圾回收器就不会消亡
System.out.println("++++++++++++++++++");
//这里如果t3、t4还没有执行完的话,主线程main阻塞,让t3、t4先执行完
//如果之前就执行完了就跳过这个join
t3.join();
t4.join();
System.out.println("--------------------");
}
}
public class MyThreadDemo extends Thread{
public MyThreadDemo(String name) {
super(name);
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
最后,总结一下,join方法是线程A加入一个线程B,线程A进入阻塞状态,而在线程B进入CPU后,时间片完了它会被踢出来,下一次抢到资源的不一定是线程B,(线程A阻塞了不会抢)也有可能是线程C、D、E等等。直到线程B运行完,线程A进入就绪状态开始抢资源。线程A抢到资源了才执行join方法后的下一条语句。如果下一条语句又是join方法,就判断调用join的线程死没死,死了就跳过,没死就把它加进来。(一般来说,这里的线程A是主线程main)
连续调用join()
并不是顺序执行这些线程。
注:本篇文章未涉及进程,如果不小心写错了,请自动换成线程