(使用CountDownlatch)
CountDownlatch概念概述CountDownlatch是JDK5后添加的同步工具,可以协调多个线程之间的同步。它允许一个或多个线程等待,直到其他线程完成。
实现原理使用计数器实现CountDownlatch的初始值是等待线程的数量。当每个计数线程执行任务完成后,计数器的值将减少一个。当计数器的值为0时,表示所有线程已完成,等待线程可以恢复继续执行任务。
CountDownlatch的用法- 其他需要一个线程 n 完成线程执行
//初始化Countdownlatch计数器Countdownlatch countDownLatch = new CountDownLatch(threadCount);//任务执行完成后,计数器减少了countdownlatch.countDown();//阻塞等待工作线程完成.await();
- 多个工作线程等待一个线程的命令,同时执行相同的任务
// 使用计数器CountDownlatch countDownLatch = new CountDownLatch(1);
// 构建一个使用给定计数初始化的CountDownLatch。public CountDownLatch(int count);/*让当前线程等待,直到锁定器倒计时为零,除非线程中断。如果当前计数为零,则该方法将立即返回。如果当前计数大于零,则禁止使用当前线程进行线程调度,并处于休眠状态,直到发生以下两种情况之一:1. 由于countdown方法的调用,计数达到零;2. 或者其他线程中断当前线程。若当前线程:1. 在进入该方法时设置中断状态;2. 或在等待时中断,抛出InteruptedException,清除当前线程的中断状态。*/public void await();除非线程中断或通过指定的等待时间,否则使当前线程等待,直到锁定器倒计时为零。若当前计数为零,则该方法立即返回值true。如果当前计数大于零,则禁止使用当前线程进行线程调度,并处于休眠状态,直到发生以下三种情况之一:1. 由于countdown方法的调用,计数达到零;2. 或者其他一些线程中断当前线程;3. 或者指定的等待时间已经过去。如果计数达到零,则该方法返回值true。若当前线程:1. 在进入该方法时设置中断状态;2. 或在等待时中断,抛出InteruptedException,清除当前线程的中断状态。在指定的等待时间之后,返回值false。若时间小于或等于零,则该方法根本不会等待。*/public boolean await(long timeout, TimeUnit unit);/** *递减锁定器的计数,如果计数为零,则释放所有等待线程。 *若当前计数大于零,则递减。若新计数为零,则出于线程调度的目的重新启用所有等待线程。 *若当前计数等于零,则不会发生任何事情。**/public void countDown();// 返回当前计数。public long getCount();// 返回标识此锁及其状态字符串public String toString();
Countdownlatch示例1.等待其他工作线程执行一个线程public static void main(String[] args) throws InterruptedException { // 使用10个线程执行任务 final int threadCount = 10; CountDownLatch countDownLatch = new CountDownLatch(threadCount); for (int i = 0; i < threadCount; i++) { new Thread(new Runnable() { @Override public void run() { // 执行具体任务 System.out.println(Thread.currentThread().getName() + " 正在运行!"); // 计数器减1 countDownLatch.countDown(); } }).start(); } // 阻塞等待线程执行结束 countDownLatch.await(); System.out.println("所有任务线程已完成"); }
运行结果如下:
2.子线程等待主线程执行,子线程执行后主线程继续执行 public static void main(String[] args) throws InterruptedException { // 共有10名选手 final int threadCount = 10; // 发号施令的计数器 CountDownLatch countDownLatch = new CountDownLatch(1); // 等待选手跑完的计数器 CountDownLatch await = new CountDownLatch(threadCount); // 使用10个工作线程执行任务 for (int i = 0; i < threadCount; i++) { new Thread(new Runnable() { @Override public void run() { try { // 阻塞等待发号命令的计数器为0 countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } // 跑步时的选手 long time = (long) (100 * Math.random()); try { Thread.sleep(time); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("选手:" + Thread.currentThread().getName() + "到达终点!耗时:" + time + "s"); /////选手的计数器减少 await.countDown(); } }).start(); } Thread.sleep(1000); System.out.println("预备-开始!"); // 将计数器减 1.运行完成后为 0 countDownLatch.countDown(); // 等待选手跑完 await.await(); System.out.println("比赛结束!"); }
运行结果如下: