如何保证线程A,B,C顺序执行,或者C在A、B后执行?

第一种方案:使用CountDownLatch工具类

CountDownLatch:是Java多线程编程中的一个同步工具类(计数锁),它允许一个或多个线程等待其他线程完成操作后再继续执行。其内部维护了一个计数器,当线程在执行任务完成后调用countDown()方法,该方法会将计数器的值减一,而等待线程通过调用await()方法来等待计数器的值变为0后才执行。

设计实现

//设计线程类

public class ThreadA implements Runnable {
    //定时锁
    private CountDownLatch latch;

    //初始化
    public ThreadA(CountDownLatch latch){
        this.latch=latch;
    }

    @Override
    public void run() {
        //1.执行
        System.out.println("A线程执行");
        //2.计数减1
        latch.countDown();
    }
}

public class ThreadB implements Runnable {
    //两个定时锁(上一个线程和当前线程)
    private CountDownLatch latch1;
    private CountDownLatch latch2;

    //初始化
    public ThreadB(CountDownLatch latch1,CountDownLatch latch2){
        this.latch1=latch1;
        this.latch2=latch2;
    }

    @Override
    public void run() {
        try {
            //1.等待上一个线程执行完成
            latch1.await();
            //2.执行
            System.out.println("B线程执行");
            //3.计数减1
            latch2.countDown();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public class ThreadC implements Runnable {
    //定时锁
    private CountDownLatch latch;

    //初始化
    public ThreadC(CountDownLatch latch){
        this.latch=latch;
    }

    @Override
    public void run() {
        try {
            //1.等待
            latch.await();
            //2.执行
            System.out.println("C线程执行");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

//测试线程A、B、C顺序执行
public class Main {
    public static void main(String[] args) {
        //创建线程A,B的定时锁,计数为1
        CountDownLatch latchA=new CountDownLatch(1);
        CountDownLatch latchB=new CountDownLatch(1);

        //创建线程A、B、C
        Thread a = new Thread(new ThreadA(latchA));
        Thread b = new Thread(new ThreadB(latchA,latchB));
        Thread c = new Thread(new ThreadC(latchB));

        //a,b,c顺序执行
        a.start();
        b.start();
        c.start();
    }
}

第二种方案:使用Semaphore同步工具

Semaphore(信号量):是一种控制并发访问资源的同步工具,用来限制同时访问某个资源的线程数量。Semaphore内部维护一个计数器,该计数器用于表示可用的许可证数量。线程在访问资源之前必须先通过acquire()方法获得许可证,如果许可证数量为0,则线程必须等待,直到有其他线程释放许可证。当线程使用完资源后,使用release()方法释放许可证,以便其他线程可以继续访问资源。

(实现原理和上个方案思想相同)

第三种方案:使用wait()、notify()和notifyAll()方法

wait() 方法:使当前线程进入等待状态

notify() 方法:唤醒在相同对象上调用 wait() 方法进入等待状态的线程中的一个线程

notifyAll() 方法:唤醒在相同对象上调用 wait() 方法进入等待状态的所有线程只有一个线程会获得(抢到)对象锁,其余线程将继续等待锁的释放)。

class Main {
    static Object lock = new Object();//对象锁
    static int threadId = 1;//当前执行线程标志

    public static void main(String[] args) {
        //线程A、B、C的标志分别为1,2,3
        //创建三个线程
        Thread a = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //获取对象锁
                    synchronized (lock) {
                        //没有到当前线程执行,则释放锁进入等待状态
                        while (threadId != 1) {
                            lock.wait();
                        }
                        //轮到当前线程执行
                        System.out.println("线程A执行");
                        threadId = 2;
                        lock.notifyAll();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread b = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    synchronized (lock) {
                        while (threadId != 2) {
                            lock.wait();
                        }
                        System.out.println("线程B执行");
                        threadId = 3;
                        lock.notifyAll();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread c = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    synchronized (lock) {
                        while (threadId != 3) {
                            lock.wait();
                        }
                        System.out.println("线程C执行");
                        threadId = 1;
                        lock.notifyAll();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        // 线程顺序执行
        a.start();
        b.start();
        c.start();
    }
}

相关推荐

  1. 线顺序循环执行

    2023-12-19 12:40:02       36 阅读
  2. C#实现定时执行+线

    2023-12-19 12:40:02       9 阅读
  3. C# 递归执行顺序

    2023-12-19 12:40:02       31 阅读
  4. 线如何知道一个线是否执行完成

    2023-12-19 12:40:02       35 阅读
  5. 线之交替输出abc

    2023-12-19 12:40:02       12 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-19 12:40:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-19 12:40:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-19 12:40:02       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-19 12:40:02       20 阅读

热门阅读

  1. LeetCode 0162. 寻找峰值:二分查找

    2023-12-19 12:40:02       49 阅读
  2. LeetCode算法练习top100:(10)贪心算法

    2023-12-19 12:40:02       29 阅读
  3. .NET Core中鉴权 Authentication Authorization

    2023-12-19 12:40:02       38 阅读
  4. ASP.NET Core Web API 缓存

    2023-12-19 12:40:02       43 阅读
  5. 树莓派通过网线连接电脑并且设置设置链接wifi

    2023-12-19 12:40:02       48 阅读
  6. Upgrading GitHub.com to MySQL 8.0

    2023-12-19 12:40:02       31 阅读
  7. iOS中宿主APP与录屏扩展进程数据传递方式

    2023-12-19 12:40:02       33 阅读
  8. do{ __HAL_RCC_GPIOH_CLK_ENABLE(); }while(0);

    2023-12-19 12:40:02       23 阅读
  9. 数据结构-顺序表的大小

    2023-12-19 12:40:02       39 阅读
  10. jquery、vue、uni-app、小程序的页面传参方式

    2023-12-19 12:40:02       31 阅读