如何让多个线程按照指定的顺序串行执行

比如:ThreadA输出0,ThreadB输出1,ThreadC输出2……同时启动线程A、B、C……最后按启动的先后顺序输出0123456……
或者
循环new Thread(),让多个线程按new的先后顺序串行执行。


参考答案:通过Thread的join()方法实现。

代码示例一:

通过Thread的join()方法实现多个线程的串行执行。每个线程会告诉下一个线程,等我先执行。

/**
 * 通过Thread的join()方法实现多个线程的串行执行
 *
 * @author wanglingqiang
 * @date 2020/7/18 下午6:14
 **/
public class Join_Test1 {

    public static void main(String[] args) {
        System.out.println("main()开始");
        Thread previousThread = Thread.currentThread();
        for (int i = 0; i < 10; i++) {
            JoinThread joinTest = new JoinThread(previousThread, i);
            joinTest.start();
            previousThread = joinTest;
        }
        System.out.println("main()结束");
    }

    static class JoinThread extends Thread {
        int i;
        Thread previousThread; //上一个线程

        public JoinThread(Thread previousThread, int i) {
            this.previousThread = previousThread;
            this.i = i;
        }

        @Override
        public void run() {
            try {
                previousThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("----previousThread=" + previousThread.getName() + ", currentThread=" + Thread.currentThread().getName() + ", i=" + i + "----");
        }
    }
    
}

运行结果:

/Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/bin/java
main()开始
main()结束
----previousThread=main, currentThread=Thread-0, i=0----
----previousThread=Thread-0, currentThread=Thread-1, i=1----
----previousThread=Thread-1, currentThread=Thread-2, i=2----
----previousThread=Thread-2, currentThread=Thread-3, i=3----
----previousThread=Thread-3, currentThread=Thread-4, i=4----
----previousThread=Thread-4, currentThread=Thread-5, i=5----
----previousThread=Thread-5, currentThread=Thread-6, i=6----
----previousThread=Thread-6, currentThread=Thread-7, i=7----
----previousThread=Thread-7, currentThread=Thread-8, i=8----
----previousThread=Thread-8, currentThread=Thread-9, i=9----

Process finished with exit code 0

变量i是for循环new Thead()时传给线程的一个参数,打印结果是01234……说明join()保证了多个线程执行时有序串行。

代码示例二:

代码示例一的基础上,加了一点注释,帮助更进一步理解join()的用法。

/**
 * 通过Thread的join()方法实现多个线程的串行执行
 *
 * @author wanglingqiang
 * @date 2020/7/18 下午6:26
 **/
public class Join_Test2 {

    public static void main(String[] args) {
        System.out.println("main()开始");
        Thread previousThread = Thread.currentThread();
        for (int i = 0; i < 10; i++) {
            JoinThread joinTest = new JoinThread(previousThread, i);
            joinTest.start();
            previousThread = joinTest;
        }
        System.out.println("main()结束");
    }

    static class JoinThread extends Thread {
        int i;
        Thread previousThread; //上一个线程

        public JoinThread(Thread previousThread, int i) {
            this.previousThread = previousThread;
            this.i = i;
        }

        @Override
        public void run() {
            try {
                System.out.println(previousThread.getName() + ".join()开始,告诉" + Thread.currentThread().getName() + "让我先");
                previousThread.join();
                System.out.println(previousThread.getName() + ".join()结束,告诉" + Thread.currentThread().getName() + "该你了");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("----previousThread=" + previousThread.getName() + ", currentThread=" + Thread.currentThread().getName() + ", i=" + i + "----");
        }
    }
}

运行结果:

/Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/bin/java
main()开始
main.join()开始,告诉Thread-0让我先
Thread-0.join()开始,告诉Thread-1让我先
Thread-1.join()开始,告诉Thread-2让我先
Thread-2.join()开始,告诉Thread-3让我先
Thread-3.join()开始,告诉Thread-4让我先
Thread-4.join()开始,告诉Thread-5让我先
Thread-5.join()开始,告诉Thread-6让我先
Thread-6.join()开始,告诉Thread-7让我先
Thread-7.join()开始,告诉Thread-8让我先
main()结束
Thread-8.join()开始,告诉Thread-9让我先
main.join()结束,告诉Thread-0该你了
----previousThread=main, currentThread=Thread-0, i=0----
Thread-0.join()结束,告诉Thread-1该你了
----previousThread=Thread-0, currentThread=Thread-1, i=1----
Thread-1.join()结束,告诉Thread-2该你了
----previousThread=Thread-1, currentThread=Thread-2, i=2----
Thread-2.join()结束,告诉Thread-3该你了
----previousThread=Thread-2, currentThread=Thread-3, i=3----
Thread-3.join()结束,告诉Thread-4该你了
----previousThread=Thread-3, currentThread=Thread-4, i=4----
Thread-4.join()结束,告诉Thread-5该你了
----previousThread=Thread-4, currentThread=Thread-5, i=5----
Thread-5.join()结束,告诉Thread-6该你了
----previousThread=Thread-5, currentThread=Thread-6, i=6----
Thread-6.join()结束,告诉Thread-7该你了
----previousThread=Thread-6, currentThread=Thread-7, i=7----
Thread-7.join()结束,告诉Thread-8该你了
----previousThread=Thread-7, currentThread=Thread-8, i=8----
Thread-8.join()结束,告诉Thread-9该你了
----previousThread=Thread-8, currentThread=Thread-9, i=9----

Process finished with exit code 0

代码示例三:

在mian()主线程里join()。每个线程都会告诉主线程,等我先执行。也能达到同样的效果。

/**
 * 在mian()主线程里join()
 *
 * @author wanglingqiang
 * @date 2020/7/18 下午6:50
 **/
public class Join_Test3 {

    public static void main(String[] args) throws InterruptedException {
        System.out.println("main()开始");
        JoinThread t1 = new JoinThread();
        t1.start();
        t1.join();
        JoinThread t2 = new JoinThread();
        t2.start();
        t2.join();
        JoinThread t3 = new JoinThread();
        t3.start();
        t3.join();
        JoinThread t4 = new JoinThread();
        t4.start();
        t4.join();
        System.out.println("main()结束");
    }

    static class JoinThread extends Thread {
        @Override
        public void run() {
            try {
                Thread.sleep(500L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName());
        }
    }

}

运行结果:

/Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/bin/java
main()开始
Thread-0
Thread-1
Thread-2
Thread-3
main()结束

Process finished with exit code 0

代码示例四:

主线程和子线程的示例,累加数字。

/**
 * 累加数字
 *
 * @author wanglingqiang
 * @date 2020/7/18 下午7:00
 **/
public class Join_Test4 {

    public static volatile int num = 0;

    public static void main(String[] args) throws InterruptedException {
        System.out.println("main()开始");
        JoinThread t = new JoinThread();
        t.start();
        //t.join();
        System.out.println("num = " + num);
        System.out.println("main()结束");
    }

    static class JoinThread extends Thread {
        @Override
        public void run() {
            for (int i = 0; i < 5; i++) {
                Join_Test4.num = Join_Test4.num + 1;
            }
        }
    }

}

运行结果:

/Library/Java/JavaVirtualMachines/jdk1.8.0_241.jdk/Contents/Home/bin/java
main()开始
num = 0
main()结束

Process finished with exit code 0

如果放开t.join()这一行的的注释,运行结果num = 5。


总结:

Thread类中的join()是使运行环境的线程wait()释放cpu的控制权让调用join()的线程执行直到完毕。比如在线程A中线程B调用了join(),表示只有当线程B执行完毕时,A线程才能继续执行。join(参数)就表示线程A等待超过参数时间就不在等待继续执行了,线程B还没执行完的话它俩就并行执行。注意join(0)不是等待0秒,而是线程A无限等待,直到线程B执行完成,即join(0)等价于join()。
它的主要作用就是同步,它可以使得线程之间并行执行变为串行执行。



猜你喜欢

转载自blog.csdn.net/WLQ0621/article/details/107433034