一 .CountDownLatch
构造函数接收一个int类型的参数作为计数器,如果想等待N个点,就传入N。当调用CountDownLatch的countDown方法时,N就会减一,直至减为零。使用await方法等待,当N的值变为零,执行await的线程继续执行。
public class DemoApplication {public static void main(String[] args)throws InterruptedException, ExecutionException {SpringApplication.run(DemoApplication.class, args);//1. 定义三线程的计数器CountDownLatch countDownLatch = new CountDownLatch(3);for(int index = 1;index<=3;index++){//2.1 执行三个子线程new Thread(new TaskRunnable(countDownLatch,index)).start();}//3.先执行await 方法前的 线程等所有线程都执行完(计数器为0),再执行主线程 countDownLatch.await();System.out.println("最后执行主线程");} } //实现Runnable 实现 run 方法 class TaskRunnable implements Runnable{private CountDownLatch countDownLatch;private Integer index;public TaskRunnable(CountDownLatch countDownLatch,Integer index){this.countDownLatch = countDownLatch;this.index = index;}@Overridepublic void run(){//2.2 每执行一个线程 ,计数器数量减一this.countDownLatch.countDown();System.out.println("第 "+this.index.toString() + "个线程,执行了。");} }
执行结果:
二.Thread.Join
Thread Join 主线程阻塞,等待该线程完成后再执行 主线程。
原理:利用while检查当前线程是否存活如果是一直阻塞wait(0)方法,当线程不存活,继续执行主线程。
public class DemoApplication {public static void main(String[] args)throws InterruptedException, ExecutionException {SpringApplication.run(DemoApplication.class, args);//Thread Join 方法 主线程阻塞,等待该线程完成后再执行 主线程。//线程1 和线程2 是串行的。能控制线程执行顺序Thread thread1 = new Thread(new TaskJoin("thread1"));thread1.start();thread1.join();Thread thread2 = new Thread(new TaskJoin("thread2"));thread2.start();thread2.join();System.out.println("主线程执行了!");} } class TaskJoin implements Runnable{private String threadName;public TaskJoin(String threadName){this.threadName = threadName;}@Overridepublic void run() {System.out.println(this.threadName + "子线程,执行了。");} }
执行结果:
三 CyclicBarrier [ˈsaɪklɪk][ˈbæriə(r)]
可循环使用的屏障。它要做的事情,让一组线程到达屏障时被阻塞,直到最后一个线程到达屏障时,屏障才会打开,所有被屏障拦截的线程才会继续运行。
默认构造方法CyclicBarrier(int parties),其参数表示屏障拦截的线程数,每个线程调用await方法告诉CyclicBarrier已经到达屏障,然后当前线程阻塞。
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);CyclicBarrier cyclicBarrier = new CyclicBarrier(3);Thread thread1 = new Thread(new TaskJoin(cyclicBarrier,"thread1"));thread1.start();Thread thread2 = new Thread(new TaskJoin(cyclicBarrier,"thread2"));thread2.start();Thread thread3 = new Thread(new TaskJoin(cyclicBarrier,"thread3"));thread3.start();} } class TaskJoin implements Runnable {private String threadName;private CyclicBarrier cyclicBarrier;public TaskJoin(CyclicBarrier cyclicBarrier,String threadName){this.threadName = threadName;this.cyclicBarrier = cyclicBarrier;}@Overridepublic void run() {System.out.println(this.threadName + "子线程,屏障点前执行了。");try {this.cyclicBarrier.await();} catch (InterruptedException e) {e.printStackTrace();} catch (BrokenBarrierException e) {e.printStackTrace();}System.out.println(this.threadName + "子线程,屏障点后执行了。");} }
执行结果:
总结:
CountDownLatch:在所有线程执行完之前,阻塞的是主线程。子线程都是并行,执行完一个释放一个。但是 无法控制线程执行顺序。
Thread.Join:每个子线程都是串行的。
CyclicBarrier:所有线程未全部到达屏障点之前,线程是不释放的。