Java多线程学习——join方法的使用
join在线程里面意味着“插队”,哪个线程调用join代表哪个线程插队先执行——但是插谁的队是有讲究了,不是说你可以插到队头去做第一个吃螃蟹的人,而是插到在当前运行线程的前面,比如系统目前运行线程A,在线程A里面调用了线程B.join方法,则接下来线程B会抢先在线程A面前执行,等到线程B全部执行完后才继续执行线程A。
而在JDK的解释中,join方法被解释成等待这个线程死亡,也就是等待这个线程全部执行完后才继续执行接下来的进程。
public class Test1 implements Runnable{ @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println(Thread.currentThread().getName()+i); } } public static void main(String[] args) throws InterruptedException { Thread thread1=new Thread(new Test1(),"线程一"); Thread thread2=new Thread(new Test1(),"线程二"); Thread thread3=new Thread(new Test1(),"线程三"); thread1.start(); thread2.start(); thread3.start(); System.out.println("------------------主线程到此-------------------"); /*thread2.join(); */ for (int i = 0; i < 20; i++) { System.out.println("主线程"+i); } } }
在上面这个例子中,在主线程里面开启了3个子线程,结果是主线程先执行完再执行其他线程。
加上让线程2先执行完再执行主线程join后
public class Test1 implements Runnable{ @Override public void run() { for (int i = 0; i < 20; i++) { System.out.println(Thread.currentThread().getName()+i); } } public static void main(String[] args) throws InterruptedException { Thread thread1=new Thread(new Test1(),"线程一"); Thread thread2=new Thread(new Test1(),"线程二"); Thread thread3=new Thread(new Test1(),"线程三"); thread1.start(); thread2.start(); thread3.start(); System.out.println("------------------主线程到此-------------------"); thread2.join(); //让线程2先执行完主线程才能继续执行 for (int i = 0; i < 20; i++) { System.out.println("主线程"+i); } } }
结果是
/** * join的用法,哪个线程调用join哪个线程就插队先执行 */ public class Test{ public static void main(String[] args) throws InterruptedException { //开启Father线程,满足Father需求 new Thread(new Father()).start(); } } class Father implements Runnable{ @Override public void run() { System.out.println("老爸要抽烟,发现没烟了,给了100块让儿子去买中华......"); Thread son=new Thread(new Son()); //让儿子去买烟 son.start(); //开启儿子线程后,儿子线程进入就绪状态等待CPU调度,不一定立即执行儿子线程,所以可能会出现儿子没把烟买回来老爸就有烟抽了 /* try { son.join(); //让儿子先插队去买烟 } catch (InterruptedException e) { e.printStackTrace(); System.out.println("儿子不见了,报警寻找"); }*/ System.out.println("老爸接过烟,把零钱给了儿子"); System.out.println("儿子很开心,出门去了游戏厅"); } } class Son implements Runnable{ @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); //此时休眠可能会让其他线程进行,出错率增加,通过join方法解决 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("赶紧去买烟"); System.out.println("回家把烟给老爸"); } }
加入了join方法后,运行结果正确
try { son.join(); //让儿子先插队去买烟 } catch (InterruptedException e) { e.printStackTrace(); System.out.println("儿子不见了,报警寻找"); }