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("儿子不见了,报警寻找");
        }

 

 

版权声明:本文为chiweiming原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/chiweiming/p/11095682.html