(面试题)模拟 主进程需要等待多个子进程结束之后再执行后续的代码的实现

解法1. Thread.join方法

import java.util.Vector;

public class Test {
    public static void main(String[] args) throws InterruptedException {
    /*
    Vector集合: JDK1.0 底层也是数组  是最早期的同步集合 也就意味着是单线程 效率低 
    			实现了list接口所以可以使用list的所有方法  
      	特有方法:
      	 void addElement(E obj) 将指定的组件添加到此向量的末尾,将其大小增加 1 
      	 Enumeration elements() 返回此向量的组件的枚举(早期的迭代器)。 
      */
        Vector vector = new Vector<>();
        for (int i = 0; i < 5; i++) {
            Thread childThread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("子线程被执行");
                }
            });
            vector.add(childThread);
            childThread.start();
        }
        for (Thread thread : vector) {
        // void join()  等待该线程终止
            thread.join();
        }
        System.out.println("主线程被执行");
    }
}

解法2.等待多线程完成的CountDownLatch

  • 1.CountDownLatch的概念: extends Object
    CountDownLatch是一个同步工具类,用来协调多个线程之间的同步
    或者说起到线程之间的通信(而不是互斥的作用)
    CountDownLatch能够使一个线程在等待另一些线程完成自己任务后,
    再继续执行.使用一个计数器进行实现,计数器初始值为线程的总数量(包括主线程).
    当每一个线程完成自己任务后,计数器的值减一.当计数器的值为0时,表示所有线程执行完成,
    然后在CountDownLatch上等待的线程可以恢复执行任务.

  • 2.CountDownLatch的典型用法:
    典型用法1:
    某一个线程开始运行前等待n个线程执行完毕.将CountDownLatch的计数器初始化
    new CountDownLatch(n),每当一个线程完成任务后,计数器的值就会减一 CountDownLatch.countDown(),当计数器的值为0时,在CountDownLatch上await()的线程就会被唤醒.
    应用场景:启动一个服务时,主线程需要等待多个组件加载完毕之后再继续执行.

    典型用法2:实现多个线程开始执行任务的最大并行性.这里时并行,不是并发,
    强调的是多个线程在某一时刻同时开始执行.类似于赛跑,将多个线程放到七点,等待发令枪,然后同时执行.
    做法是初始化一个共享的CountDownLatch(1),将其计数器初始化为1.多个线程开始执行任务前首先CountDownLatch.await().当主线程调用countDown()时,计数器变为0,多个线程同时被唤醒.

  • 3.CountDownLatch的不足:
    CountDownLatch是一次性的,计数器的值只能在构造方法中初始化一次,之后没有任何机制能够再次对其设置值,
    当CountDownLatch使用完毕后,不能再次被调用.

 public static void main(String[] args) throws InterruptedException {
        //创建CountDownLatch并初始化为5
        CountDownLatch latch = new CountDownLatch(5);
        for (int i = 0; i < 5; i++) {
            Thread childthread = new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("子线程开始执行");
                    //计数器递减,为0时释放所有线程
                    latch.countDown();
                }
            });
            childthread.start();
        }
        //设置主线程等待
        latch.await();
        System.out.println("主线程开始执行");
    }

你可能感兴趣的:(瞎搞)