结论:A 线程调用 B 线程对象的 join 方法,则 A 线程会被阻塞,直到 B 线程 挂掉 (Java Doc 原话: Watis for this thread to die)
上代码分析
public class Station extends Thread{
public Station(String name) {
super(name);
}
static int tick = 30;
int tickets=0;
// 创建一个静态钥匙
static Object ob = "aa";
@Override
public void run() {
while (tick > 0) {
synchronized (ob) {// 锁
if (tick > 0) {
tickets= (int) (Math.random()*10);//随机票数
if(tickets>tick)
tickets=tick;
tick=tick-tickets;
System.out.println(getName() + "卖出了" + tickets + "张票");
System.out.println("还剩"+tick+"张");
}
}
try {
sleep(1000);//休息
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(getName()+"卖完啦");
}
}
public class MainC {
public static void main(String[] args) throws InterruptedException {
Station station1=new Station("窗口1");
Station station2=new Station("窗口2");
Station station3=new Station("窗口3");
Station station4=new Station("窗口4");
Station station5=new Station("窗口5");
station1.start();
station2.start();
station3.start();
station4.start();
station5.start();
}
}
不加join方法的运行结果
窗口2卖出了3张票
还剩27张
窗口4卖出了5张票
还剩22张
窗口3卖出了1张票
还剩21张
窗口1卖出了9张票
还剩12张
窗口5卖出了2张票
还剩10张
窗口5卖出了5张票
还剩5张
窗口2卖出了2张票
还剩3张
窗口4卖出了3张票
还剩0张
窗口1卖完啦
窗口2卖完啦
窗口5卖完啦
窗口4卖完啦
窗口3卖完啦
可以看出,不加join方法的时候,5个线程是 并行执行的
现在加上join方法
看下结果
可以看出当线程运行到
station3.join();的时候,主线程main线程阻塞挂起(即main线程放弃cpu控制权,并返回station3线程继续执行直到线程station3执行完毕),
实际运行的只有前三个线程,所以只有station3执行完成之后才会继续往下执行,然而前三个线程已经把任务执行完了
join()就是join(0)指的是无限等待即join(0)
上源码
/**
* Waits at most {@code millis} milliseconds for this thread to //等待设定的时间直到这个线程死亡,join(0)就是一直等待下去
* die. A timeout of {@code 0} means to wait forever.
*
* <p> This implementation uses a loop of {@code this.wait} calls
* conditioned on {@code this.isAlive}. As a thread terminates the
* {@code this.notifyAll} method is invoked. It is recommended that
* applications not use {@code wait}, {@code notify}, or
* {@code notifyAll} on {@code Thread} instances.
*
* @param millis
* the time to wait in milliseconds
*
* @throws IllegalArgumentException
* if the value of {@code millis} is negative
*
* @throws InterruptedException
* if any thread has interrupted the current thread. The
* <i>interrupted status</i> of the current thread is
* cleared when this exception is thrown.
*/
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);//一直等
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
而wait()的意思是让运行这行代码的线程等待(在这里就是main线程等待),
而不是让station3这个线程等待
总结:线程A中调用线程B的join方法时,线程A会挂起,直到线程B执行完毕后,才会继续执行线程A。
原理:线程A中调用线程B的join方法时,会使线程A调用自己的wait方法从而进行阻塞线程A,以达到让线程B执行的目的