美文网首页
如何让多个线程顺序执行

如何让多个线程顺序执行

作者: 曹仁不会飞 | 来源:发表于2021-04-19 18:32 被阅读0次

先说一下为什么会有这样的要求,如果是简单的要求按顺序执行代码,直接一行行写下来就行了。但是接口调用我们一般都放在工作线程里面,而且有时候需要拿一个接口返回的参数去请求另一个接口,这就需要控制线程按某种顺序执行。

方法1:join()

public class A1 extends Thread {
    @Override
    public void run() {
        try {
            System.out.println("--- thread A1 start ---");
            sleep((long) (Math.random() * 30));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("--- thread A1 end ---");
    }
}

public class A2 extends Thread {
    @Override
    public void run() {
        try {
            System.out.println("--- thread A2 start ---");
            sleep((long) (Math.random() * 30));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("--- thread A2 end ---");
    }
}

public class A3 extends Thread {
    @Override
    public void run() {
        try {
            System.out.println("--- thread A3 start ---");
            sleep((long) (Math.random() * 30));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("--- thread A3 end ---");
    }
}

public class OrderTest {
    public static void main(String[] args) {
        try {
            A1 a1 = new A1();
            a1.start();
            a1.join();
            A2 a2 = new A2();
            a2.start();
            a2.join();
            A3 a3 = new A3();
            a3.start();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
// 控制台输出:
--- thread A1 start ---
--- thread A1 end ---
--- thread A2 start ---
--- thread A2 end ---
--- thread A3 start ---
--- thread A3 end ---

a1.start()使a1进入就绪状态,a1和主线程都可能抢到CPU执行权,a1.join()使 a1 线程独占CPU,主线程要等a1执行完才能执行a2的初始化和a2.start()等后续代码。

另外,把a2的初始化和a2.join()放在a3run()里面的第一行(即执行a3的逻辑代码前),把a1的初始化和a1.join()放在a2run()里面的第一行,也能让a1a2a3顺序执行,效果和上述代码相同。

方法2:wait() & notify()

public class B1 extends Thread{
    @Override
    public void run() {
        synchronized (this){
            try {
                System.out.println("--- thread B1 start ---");
                sleep((long) (Math.random() * 30));
                System.out.println("--- thread B1 end ---");
                notify();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class B2 extends Thread {
    @Override
    public void run() {
        B1 b1 = new B1();
        b1.start();
        synchronized (b1){
            try {
                b1.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        synchronized (this){
            try {
                System.out.println("--- thread B2 start ---");
                sleep((long) (Math.random() * 30));
                System.out.println("--- thread B2 end ---");
                notify();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class B3 extends Thread {
    @Override
    public void run() {
        B2 b2 = new B2();
        b2.start();
        synchronized (b2){
            try {
                b2.wait();
                System.out.println("--- thread B3 start ---");
                sleep((long) (Math.random() * 30));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("--- thread B3 end ---");
        }
    }
}

public class OrderTest {
    public static void main(String[] args) {
        new B3().start();
    }
}
// 控制台输出:
--- thread B1 start ---
--- thread B1 end ---
--- thread B2 start ---
--- thread B2 end ---
--- thread B3 start ---
--- thread B3 end ---

需要注意的是,线程B2中调用b1.wait()的时候不是让b1对象等待,而是让获取到b1对象同步锁的当前线程等待。这里面的「当前线程」指的就是线程B2了。

线程B1中的notify(),唤醒的是在当前对象上等待的线程(其实这里的notify()相当于this.notiify())。

B2线程的run()里面,执行第一个synchronized代码块的时候,当前线程wait了,当被唤醒的时候继续执行后续代码(即第二个synchronized代码块);B3被唤醒后执行b2.wait()后面的代码:System.out.println("--- thread B3 start ---"); 等。

方法3:线程池

public class OrderTest {
    public static void main(String[] args) {
        A1 a1 = new A1();
        A2 a2 = new A2();
        A3 a3 = new A3();
        ExecutorService single = Executors.newSingleThreadExecutor();
        single.submit(a1);
        single.submit(a2);
        single.submit(a3);
        single.shutdown();
    }
}
// 控制台输出:
--- thread A1 start ---
--- thread A1 end ---
--- thread A2 start ---
--- thread A2 end ---
--- thread A3 start ---
--- thread A3 end ---

newSingleThreadExecutor只包含一个线程,而且可以保证线程按顺序执行。

方法4

最容易想到的办法,在一个线程的run()里面的结尾处初始化并启动另一个线程(thread.start()),这个简单就补贴代码了。

相关文章

  • 如何让多个线程顺序执行

    先说一下为什么会有这样的要求,如果是简单的要求按顺序执行代码,直接一行行写下来就行了。但是接口调用我们一般都放在工...

  • scrapy如何顺序执行多个爬虫

    scrapy如何单线程顺序执行多个爬虫,刚开始我天真的以为将多个excute顺序罗列就能依次执行每个爬虫了,代码如...

  • Java面试-多线程问题整理

    1.如何让线程顺序执行: 1.thread.join 方法,可以让主线程等待子线程执行完之后,再执行。 jion方...

  • 如何让线程顺序执行

    需求 让多个线程按照顺序执行 有人说,直接按照顺序调用start方法不就好了吗,来看看案例 效果如下 多次运行,会...

  • java进程、线程概述

    所谓线程,就是一个程序运行中,包含了多个顺序执行流(多个功能的实现),其中每个执行流就是一个线程。 进程,程序执行...

  • 多线程学习(三)

    一.创建和等待多个线程 //a):多个线程执行顺序是乱的,跟操作系统内部对线程的运行调度机制有关;//b):主线程...

  • Java线程通信-线程协调API

    线程通信 想要实现多个线程之间的协同,如:线程执行顺序,获取某个线程执行结果等,则需要使用线程之间互相通信。 文件...

  • java并发编程学习--控制线程顺序

    目标 多个线程如何控制先后顺序 学习总结 通过join控制,原理,让父线程等待子线程结束之后才能继续运行,看下线程...

  • GCD指南

    GCD指南 基本概念 串行:多个任务在一条线程上顺序执行。 并发:多个任务在多条线程上同时执行。 同步:立即在当前...

  • iOS GCD 常用功能

    获取主队列 异步执行 会开新线程 创建串行队列 开一个线程 顺序执行 1 和 2 创建并行队列 创建多个线程 ...

网友评论

      本文标题:如何让多个线程顺序执行

      本文链接:https://www.haomeiwen.com/subject/bzcwlltx.html