CountDownLatch的使用

发布时间:2023-12-13 11:16:00

(使用CountDownlatch)

CountDownlatch概念概述

CountDownlatch是JDK5后添加的同步工具,可以协调多个线程之间的同步。它允许一个或多个线程等待,直到其他线程完成。

实现原理

使用计数器实现CountDownlatch的初始值是等待线程的数量。当每个计数线程执行任务完成后,计数器的值将减少一个。当计数器的值为0时,表示所有线程已完成,等待线程可以恢复继续执行任务。

CountDownlatch的用法
  1. 其他需要一个线程 n 完成线程执行
    //初始化Countdownlatch计数器Countdownlatch countDownLatch = new CountDownLatch(threadCount);//任务执行完成后,计数器减少了countdownlatch.countDown();//阻塞等待工作线程完成.await();
  2. 多个工作线程等待一个线程的命令,同时执行相同的任务
    // 使用计数器CountDownlatch countDownLatch = new CountDownLatch(1);
Countdownlatch函数
// 构建一个使用给定计数初始化的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("所有任务线程已完成");    }

运行结果如下:image.png

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("比赛结束!");    }

运行结果如下:image.png

上一篇 【sql优化】left join条件放on和where后的区别
下一篇 File类的基础使用(二) - 创建功能

文章素材均来源于网络,如有侵权,请联系管理员删除。

标签: Java教程Java基础Java编程技巧面试题Java面试题