【面试题】有线程A,B,C,C 要等A和B都执行完了才执行,怎么实现?

有线程A,B,C,C 要等A和B都执行完了才执行,怎么实现?

LockSupport + AtomicInteger

​ 先执行线程C,用 park() 挂起线程C,线程A、B各自执行完成时,flag 减1并判断是否为0,若为0则用unpark©给线程C颁发许可。

  • LockSupport.park() 函数表示挂起当前线程
  • LockSupport.unpark© 函数表示解除线程c的阻塞状态
  • AtomicInteger.decrementAndGet() 函数表示将该变量减一,并返回当前变量值(线程安全的原子类)
public static void main(String[] args) {

        AtomicInteger flag = new AtomicInteger(2);

        Thread c =  new Thread(()->{
            System.out.println("线程C开启,等待线程A、B执行完成才继续执行");
            LockSupport.park();
            System.out.println("线程C开始执行");
        });
        c.start();

        new Thread(()->{
            System.out.println("线程A开始执行");
            try {
                TimeUnit.SECONDS.sleep(new Random().nextInt(10));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程A执行完成");
            if (flag.decrementAndGet() == 0){
            	//唤醒指定线程
                LockSupport.unpark(c);
            }
        }).start();
        
        new Thread(()->{
            System.out.println("线程B开始执行");
            try {
                TimeUnit.SECONDS.sleep(new Random().nextInt(10));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("线程B执行完成");
            if (flag.decrementAndGet() == 0){
                LockSupport.unpark(c);
            }
        }).start();
    }

CountDownLatch

​ CountDownLatch 有一个计数器,countDown() 方法对计数器做减操作,await 方法等待计数器达到0。所有await的线程都会阻塞直到计数器为0或者等待线程中断或者超时.

  • latch.countDown() 函数将计数器减一
  • latch.await() 函数表示,当计数器为0时才接着往下执行,否则陷入阻塞
public static void main(String[] args) {

        CountDownLatch  latch = new CountDownLatch(2);

        new Thread(() -> {
            System.out.println("线程A开始执行");
            try {
                TimeUnit.SECONDS.sleep(new Random().nextInt(10));
                latch.countDown();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("线程A执行完成");
        }).start();

        new Thread(() -> {
            System.out.println("线程B开始执行");
            try {
                TimeUnit.SECONDS.sleep(new Random().nextInt(10));
                latch.countDown();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("线程B执行完成");

        }).start();

        new Thread(() -> {
            System.out.println("线程C开启,等待线程A、B执行完成才继续执行");
            try {
                latch.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("线程C执行完成");

        }).start();

    }

CyclicBarrier

​ CyclicBarrier 与 CountDownLatch 类似 ,它能阻塞一组线程全部到某个状态再同时执行。 CyclicBarrier 与 CountDownLatch 的关键区别在于,所有的线程必须全部到达位置,才能继续执行。 CountDownLatch 用于等待事件,而 CyclicBarrier 用于等待其他线程,在任意一个线程没有完成之前,所有线程都不能继续执行。

  • barrier.await() 函数使当前线程阻塞,直到相应数量的线程都执行到了该函数,才会将所有线程解锁,往下执行
public static void main(String[] args) {

        CyclicBarrier barrier = new CyclicBarrier(3);

        //只有所有线程执行到了 await(),所有线程才会继续往下执行

        new Thread(() -> {
            System.out.println("线程A开始执行");
            try {
                //执行业务
                TimeUnit.SECONDS.sleep(new Random().nextInt(10));
                System.out.println("线程A执行完成,等待其它线程一起冲破栅栏");
                barrier.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("线程A执行完成");
        }).start();

        new Thread(() -> {
            System.out.println("线程B开始执行");
            try {
                //执行业务
                TimeUnit.SECONDS.sleep(new Random().nextInt(10));
                System.out.println("线程B执行完成,等待其它线程一起冲破栅栏");
                barrier.await();
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("线程B执行完成");

        }).start();

        new Thread(() -> {
            try {
                System.out.println("线程C开启,等待线程AB执行完成一起冲破栅栏");
                barrier.await();
                //执行业务
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println("线程C执行完成");

        }).start();

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值