join:合并线程,也可以叫插队线程,让此线程执行完成后,再执行其他线程,其他线程阻塞,它和sleep不同的是,join是个成员方法,写那个线程体中,那个线程体被阻塞。
就像上图里面的黄色的车一样,黄色的车插队,非要等黄色的车走了后面的车才能走,后面的车被阻塞了。
看代码
package com.cb.thread.day02;
/*
* join:合并线程 插队线程
*/
public class BlockedJoin01 {
public static void main(String[] args) throws InterruptedException {
Test t = new Test();
Thread c = new Thread(t);
c.start();
for (int i = 0; i < 10; i++) {
System.out.println("main-->"+i);
if (i==5) {
c.join();//插队 t线程插main的队,main线程被阻塞了
}
}
}
}
class Test implements Runnable{
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println("test-->"+i);
}
}
}
运行结果:当线程t和mian线程都进入了 线程队列中,cpu先调用main线程,当mian线程运行到5时,运行t.join,然后t线程就插队了,而main线程就被阻塞了,一定要等t线程运行完进入死亡状态后,main线程才能运行。
案例二
package com.cb.thread.day02;
public class BlockedJoin02 {
public static void main(String[] args) {
System.out.println("爸爸和儿子习烟的故事");
new Thread(new Fatner()).start();
}
}
class Fatner extends Thread{
@Override
public void run() {
System.out.println("想抽烟,发现没了");
System.out.println("想让儿子去买蓝楼");
Thread son = new Thread(new Son());
son.start();
try {
son.join(); //儿子插老爸的队,老爸被阻塞,非要等儿子把烟拿会来,老爸在能抽
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("老爸接过烟,把零钱给了儿子");
}
}
class Son extends Thread{
@Override
public void run() {
System.out.println("拿过钱去买烟");
System.out.println("路边有个游戏厅,玩了10秒钟");
for (int i = 1; i <=10; i++) {
System.out.println(i+"秒过去。。。");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("赶紧买烟去了");
System.out.println("手拿蓝楼回来了");
}
}
运行结果: