非物质文化遗产网站怎么做网站用户反馈
news/
2025/9/22 16:06:58/
文章来源:
非物质文化遗产网站怎么做,网站用户反馈,wordpress 建站 视频 百度云,环保材料东莞网站建设一、什么是CountDownLatch
CountDownLatch中count down是倒数的意思#xff0c;latch则是门闩的含义。整体含义可以理解为倒数的门栓。
CountDownLatch的作用也是如此#xff0c;在构造CountDownLatch(int count)#xff1a;的时候需要传入一个整数count#xff0c;在这个…一、什么是CountDownLatch
CountDownLatch中count down是倒数的意思latch则是门闩的含义。整体含义可以理解为倒数的门栓。
CountDownLatch的作用也是如此在构造CountDownLatch(int count)的时候需要传入一个整数count在这个整数“倒数”到0之前主线程需要等待在门口而这个“倒数”过程则是由各个执行线程驱动的每个线程执行完一个任务“倒数”一次。
总结来说CountDownLatch是Java中一个多线程工具类用于控制线程的顺序可以让主线程等待其他线程完成任务之后再继续执行或者让多个线程之间相互等待。
二、主要方法
CountDownLatch(int count)构造方法创建一个新的 CountDownLatch 实例用给定的计数初始化。参数 count 表示线程需要等待的任务数量。
int numberOfTasks 5;
CountDownLatch latch new CountDownLatch(numberOfTasks);void await()使当前线程等待直到计数器值变为0除非线程被 interrupted。如果计数器的值已经为0则此方法立即返回。在实际应用中通常在主线程中调用此方法等待其他子线程完成任务。(会使线程休眠直到countDownLatch的值递减到0才会重新就绪)
latch.await();boolean await(long timeout, TimeUnit unit)使当前线程等待直到计数器值变为0或者指定的等待时间已到或者线程被 interrupted。如果计数器的值已经为0则此方法立即返回。
参数 timeout 是指定的等待时间参数 unit 是 timeout 的单位如秒、毫秒等。
此方法返回一个布尔值表示在等待时间内计数器是否变为0。
latch.await(5, TimeUnit.SECONDS);这里需要注意的是await()方法并没有规定只能有一个线程执行该方法如果多个线程同时执行await()方法那么这几个线程都将处于等待状态并且以共享模式享有同一个锁。
void countDown()递减计数器的值。如果计数器的结果为0 则释放所有等待的线程。在实际应用中通常在线程完成任务后调用此方法。
latch.countDown();这里需要注意的是countDown()方法并没有规定一个线程只能调用一次当同一个线程调用多次countDown()方法时每次都会使计数器减一
long getCount()获取当前计数的值。返回当前 CountDownLatch 实例内部的计数值。
long remainingCount latch.getCount();三、优缺点
优点
简化了线程间的通信和同步。在某些并发场景中需要等待其他线程完成任务后才能继续执行使用 CountDownLatch 可以简化这种操作而不需要复杂的锁和等待/通知机制。提高性能。由于 CountDownLatch 可以让线程在完成任务后立即递减计数值而不需要等待其他线程完成任务因此可以减少阻塞提高程序运行性能。支持灵活的计数。可以通过创建不同的 CountDownLatch 实例实现对多个线程任务计数。
缺点
单次使用。CountDownLatch 的计数值无法重置。一旦计数值到达零它就不能再被使用了。在需要重复使用的场景中可以选用 CyclicBarrier 或 Semaphore。没有返回值。CountDownLatch 无法获得执行任务的线程所返回的结果。如果需要收集线程执行结果可以考虑使用 java.util.concurrent.Future 和 java.util.concurrent.ExecutorService。
四、使用场景
启动多个线程执行并行任务主线程等待所有并行任务完成后继续执行。 例如在测试中准备数据阶段需要同时查询多个子系统的数据和处理等待处理结束后再进行下一步操作。控制线程的执行顺序。一个线程需要等待其他线程的结果或者完成任务后才能继续执行。 例如一个文件解压缩程序首先需要下载文件下载完成后解压文件。实现一个计数器允许一个或多个线程等待直到计数器为0。这对于在系统初始化时需要等待资源加载或者初始化的场景十分有用。 例如等待加载配置文件、启动连接池等操作完成后才开始处理其他任务。
五、示例代码
一个简单示例代码
在这个例子中创建了5个线程并让每个线程睡眠1秒钟表示完成一个任务。在每个线程完成任务后调用了countDown()方法计数器减1。
在主线程中调用了await()方法等待所有线程完成任务。当所有线程的计数器都减为0时主线程才会继续执行输出All tasks done。
import java.util.concurrent.CountDownLatch;public class CountDownLatchExample {public static void main(String[] args) throws InterruptedException {int n 5; // 等待5个线程完成任务CountDownLatch countDownLatch new CountDownLatch(n);for (int i 0; i n; i) {Thread t new Thread(() - {try {System.out.println(Thread.currentThread().getName() is working);Thread.sleep(1000);System.out.println(Thread.currentThread().getName() done);countDownLatch.countDown(); // 计数器减1} catch (InterruptedException e) {e.printStackTrace();}});t.start();}countDownLatch.await(); // 等待其他线程完成任务System.out.println(All tasks done);}
}输出结果
Thread-0 is working
Thread-1 is working
Thread-2 is working
Thread-3 is working
Thread-4 is working
Thread-2 done
Thread-1 done
Thread-0 done
Thread-4 done
Thread-3 done
All tasks done启动一个服务时主线程需要等待多个组件加载完毕之后再继续执行
package base.threadabout.multhread.countdownlatch;import java.util.concurrent.*;/*** CountDownLatch常用方法await(),await(long,TimeUnit),countDown()* await()会使线程休眠直到countDownLatch的值递减到0才会重新就绪* await(long, TimeUnit) 休眠直到countDownLatch的值递减到0或休眠时间结束* 大概作用等所有线程某些线程都执行完了再统一执行某个具体功能*/
public class MainLoadingService {public static void main(String[] args) throws InterruptedException {CountDownLatch cdl new CountDownLatch(5);ExecutorService pool Executors.newFixedThreadPool(5);for (int i 0; i 5; i) {Loading runnable new Loading(cdl);pool.execute(runnable);}// 线程全部跑完的标志System.out.println(等待子线程加载组件...);cdl.await();System.out.println(所有组件加载完毕继续执行...);pool.shutdown();}
}class Loading implements Runnable {private CountDownLatch countDownLatch;public Loading(CountDownLatch countDownLatch) {this.countDownLatch countDownLatch;}Overridepublic void run() {// 处理业务String name Thread.currentThread().getName();System.out.println(子线程: name 正在加载组件...);// 业务处理完毕countDownLatch-1countDownLatch.countDown();}
}结果
等待子线程加载组件...
子线程:pool-1-thread-1正在加载组件...
子线程:pool-1-thread-2正在加载组件...
子线程:pool-1-thread-3正在加载组件...
子线程:pool-1-thread-4正在加载组件...
子线程:pool-1-thread-5正在加载组件...
所有组件加载完毕关闭线程池pool...示例
主线程定义new CountDownLatch(1)。每个子线程先执行await()进入等待。等待所有子线程都开启主线程执行countDown()能确保所有子线程同时开始处理任务。
类似于赛跑子线程是运动员await是运动员的预备阶段主线程是裁判countDown是裁判的发令枪。枪响运动员才能跑。
package base.threadabout.multhread.countdownlatch;import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class RaceGame {public static void main(String[] args) throws InterruptedException {ExecutorService pool Executors.newFixedThreadPool(5);CountDownLatch countDownLatch new CountDownLatch(1);for (int i 0; i 5; i) {Player player new Player(i, countDownLatch);pool.execute(player);}Thread.sleep(1000);System.out.println(所有选手各就位.....GO!);countDownLatch.countDown();pool.shutdown();}static class Player implements Runnable{private int id;private CountDownLatch countDownLatch;public Player(int id, CountDownLatch countDownLatch) {this.id id;this.countDownLatch countDownLatch;}Overridepublic void run() {System.out.println(参赛选手[ id ]号准备就绪...);try {countDownLatch.await();} catch (InterruptedException e) {e.printStackTrace();}System.out.println(参赛选手[ id ]号到达终点...);}}
}结果
参赛选手[0]号准备就绪...
参赛选手[1]号准备就绪...
参赛选手[2]号准备就绪...
参赛选手[3]号准备就绪...
参赛选手[4]号准备就绪...
所有选手各就位.....GO!
参赛选手[1]号到达终点...
参赛选手[3]号到达终点...
参赛选手[0]号到达终点...
参赛选手[2]号到达终点...
参赛选手[4]号到达终点...示例代码
下面的示例展示了一个简单的网站爬虫它使用 CountDownLatch 在主线程中等待其他爬虫线程完成任务。在这个例子中我们要爬取一组网站的内容在主线程中等待所有爬虫任务完成。
首先我们创建一个 URLs 列表包含多个网站 URL。
然后我们使用 CountDownLatch 实例 latch 来跟踪待完成的爬虫任务数量。
接着我们遍历 URL 列表为每个 URL 创建一个新的 Crawler 线程。Crawler 类实现了 Runnable 接口用于读取指定 URL 的网页内容。在完成任务后它调用 latch.countDown() 方法减少计数值。
最后在主线程中我们调用 latch.await() 方法等待所有爬虫线程完成任务。当所有任务完成时打印一条消息表示爬虫任务已完成。
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;public class WebCrawler {private static class Crawler implements Runnable {private final String url;private final CountDownLatch latch;public Crawler(String url, CountDownLatch latch) {this.url url;this.latch latch;}Overridepublic void run() {try {URL urlObject new URL(url);BufferedReader in new BufferedReader(new InputStreamReader(urlObject.openStream()));String inputLine;StringBuilder content new StringBuilder();while ((inputLine in.readLine()) ! null) {content.append(inputLine);content.append(\n);}in.close();System.out.println(爬取 url 成功, 内容大小: content.length() 字符);} catch (Exception e) {System.err.println(爬取 url 失败, 原因: e.getMessage());} finally {latch.countDown();}}}public static void main(String[] args) throws InterruptedException {ListString urls new ArrayList();urls.add(https://github.com/);urls.add(https://stackoverflow.com/);urls.add(https://www.zhihu.com/);urls.add(https://www.reddit.com/);urls.add(https://www.linkedin.com/);CountDownLatch latch new CountDownLatch(urls.size());System.out.println(开始爬虫任务...);for (String url : urls) {new Thread(new Crawler(url, latch)).start();}latch.await();System.out.println(所有爬虫任务都已完成!);}
}运行结果
开始爬虫任务...
爬取 https://www.zhihu.com/ 成功, 内容大小: 37783 字符
爬取 https://github.com/ 成功, 内容大小: 227576 字符
爬取 https://stackoverflow.com/ 成功, 内容大小: 171290 字符
爬取 https://www.linkedin.com/ 成功, 内容大小: 12603 字符
爬取 https://www.reddit.com/ 失败, 原因: Read timed out
所有爬虫任务都已完成!稍复杂点的示例代码
在这个例子中我们将模拟一个简单的赛车游戏
其中有一个倒计时开始。一旦倒计时结束赛车就开始比赛当所有赛车完成比赛时主线程打印一条消息。
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;public class CountDownLatchAdvancedDemo {public static void main(String[] args) throws InterruptedException {int numberOfRacers 5;CountDownLatch startSignal new CountDownLatch(1);CountDownLatch finishSignal new CountDownLatch(numberOfRacers);// 创建赛车线程for (int i 0; i numberOfRacers; i) {//这里虽然start但是由于前面new了startSignal并且实现类中await的影响会等待new Thread(new Racer(startSignal, finishSignal)).start();}// 模拟倒计时System.out.println(倒计时开始...);for (int i 3; i 0; i--) {System.out.println(倒计时: i);TimeUnit.SECONDS.sleep(1);}System.out.println(比赛开始);startSignal.countDown(); // 启动信号// 等待所有赛车完成比赛finishSignal.await();System.out.println(所有赛车都完成了比赛);}static class Racer implements Runnable {private CountDownLatch startSignal;private CountDownLatch finishSignal;public Racer(CountDownLatch startSignal, CountDownLatch finishSignal) {this.startSignal startSignal;this.finishSignal finishSignal;}Overridepublic void run() {try {// 等待开始信号startSignal.await();// 正在比赛System.out.println(Thread.currentThread().getName() 开始比赛...);Thread.sleep((long) (Math.random() * 10000));System.out.println(Thread.currentThread().getName() 完成比赛!);} catch (InterruptedException e) {e.printStackTrace();} finally {// 完成比赛后递减完成信号计数finishSignal.countDown();}}}
}在这个例子中我们创建了两个 CountDownLatch
一个用于开始信号 (startSignal)另一个用于完成信号 (finishSignal)。创建赛车线程时它们都需要等待开始信号。
当倒计时结束时调用 startSignal.countDown()开始信号变为0并表示比赛开始。
每个线程在模拟赛车完成比赛后调用 finishSignal.countDown() 减少完成信号计数。
主线程使用 finishSignal.await() 等待所有赛车线程都完成比赛。当计数值变为 0 时主线程将打印一条消息表示所有赛车都完成了比赛。
运行结果 倒计时开始...
倒计时: 3
倒计时: 2
倒计时: 1
比赛开始
Thread-4 开始比赛...
Thread-2 开始比赛...
Thread-0 开始比赛...
Thread-1 开始比赛...
Thread-3 开始比赛...
Thread-4 完成比赛!
Thread-1 完成比赛!
Thread-0 完成比赛!
Thread-2 完成比赛!
Thread-3 完成比赛!
所有赛车都完成了比赛
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/909582.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!