CountDownLatch解析和应用示例
来源:互联网 发布:windows arp欺骗工具 编辑:程序博客网 时间:2024/06/10 16:31
前言
在日常处理线程同步问题的时候我们经常联想到的可能有下面几种办法:
1.synchronized关键字
2.Java5引入的java.util.concurrent.locks包的显示锁
3.CountDownLatch
今天要说的CountDownLatch是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的任务后,计数器的值就会减1。当计数器值到达0时,它表示所有的线程已经完成了任务,然后在闭锁上等待的线程就可以恢复执行任务。
简单的来说,CountDownLatch就是可以通过这种计数的方式控制线程的执行临界区,举个例子:
我有事务A、B、C、D需要完成,A、B、C是D的前置条件,D事务必须要等A、B、C全部完成后才能开始。
我们就可以通过CountDownLatch去管理这种执行上的先后问题。
实现
打开java.util.concurrent包的CountDownLatch类,可以看到有以下成员方法。
几个关键的方法:
- CountDownLatch(int)
初始化一个CountDownLatch,设置闩值,如果闩值未减到0,不执行后续语句
- await()
判断CountDownLatch的值是否已经减到了0,没有的话将一直处于等待状态
- countDown()
供线程完成自己的业务后调用,CountDownLatch初始化的值减1
- getCount()
获取当前CountDownLatch的值
看了CountDownLatch具体的实现方法,关于前言中的例子如何实现,是不是就已经胸有成竹了,我们只需要做下面几件事。
1.为A、B、C三个事务各声明一个线程去执行相关业务代码。
2.声明一个初始值为3的CountDownLatch,用来计数。
3.A、B、C三个事务的线程在执行完成后调用countDown()方法。
4.通过CountDownLatch的await()方法判断A、B、C是否均已完成。
示例
针对上面的例子,模拟了一个应用场景。
假设某个新上线项目的部署需要先启动网络服务、DNS服务以及数据服务,在其他三个服务启动前,部署事务一直处于闭锁状态。
- Service.java
服务类,声明3个服务对象。
package countDownLatch.service;/** * * @author lenovo * 模拟服务启动 */public class Service { //服务名 private String serviceName; //服务启动所需时间 private Long startUpMills; public Service(String serviceName, Long startUpMills){ this.serviceName = serviceName; this.startUpMills = startUpMills; } public void startUpService(){ try{ System.out.println("服务"+serviceName+"启动中..."); Thread.sleep(startUpMills); }catch(InterruptedException ie){ ie.printStackTrace(); } System.out.println("服务"+serviceName+"启动完毕..."); }}
- ServiceStartupTestThread.java
服务线程类,将每个服务的启动工作交付给线程执行,并完成服务启动前后的相关操作。
package countDownLatch.service;import java.util.concurrent.CountDownLatch;public class ServiceStartupTestThread implements Runnable{ //当前线程内的服务对象 private Service service; //countDownLatch计数器 private CountDownLatch cdl; ServiceStartupTestThread(Service service, CountDownLatch cdl){ this.service = service; this.cdl = cdl; } @Override public void run() { //处理线程绑定的业务逻辑 service.startUpService(); //处理完毕CountDownLatch-1 cdl.countDown(); }}
- StartupProject.java
启动项目主方法,在这里判断三个服务是否均已启动完毕。
package countDownLatch.service;import java.util.ArrayList;import java.util.List;import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class StartupProject { public static void main(String[] args) { CountDownLatch cdl = new CountDownLatch(3); //创建服务对象 Service netWork = new Service("网络服务", (long)(Math.random()*5000+1000)); Service dns = new Service("DNS服务", (long)(Math.random()*5000+1000)); Service dataSource = new Service("数据服务", (long)(Math.random()*5000+1000)); //为每一个服务提供执行线程 ServiceStartupTestThread netWorkThread = new ServiceStartupTestThread(netWork, cdl); ServiceStartupTestThread dnsThread = new ServiceStartupTestThread(dns, cdl); ServiceStartupTestThread dataSourceThread = new ServiceStartupTestThread(dataSource, cdl); //创建线程list List<ServiceStartupTestThread> serviceList = new ArrayList<ServiceStartupTestThread>(); serviceList.add(netWorkThread); serviceList.add(dnsThread); serviceList.add(dataSourceThread); //创建一个容量适配的连接池 ExecutorService executor = Executors.newFixedThreadPool(serviceList.size()); for(ServiceStartupTestThread t : serviceList){ executor.execute(t); } //关闭连接池 executor.shutdown(); try { cdl.await(); System.out.println("所有服务已经启动完毕!"); //method()启动项目部署... } catch (InterruptedException e) { e.printStackTrace(); } }}
运行结果:
参考文章
感谢!
http://www.importnew.com/15731.html
什么时候使用CountDownLatchhttp://blog.csdn.net/jackfrued/article/details/44499227
关于Java并发编程的总结和思考
- CountDownLatch解析和应用示例
- java CountDownLatch原理和示例
- CountDownLatch和CyclicBarrier使用示例
- CountDownLatch应用
- CountDownLatch应用
- CountDownLatch和CyclicBarrier的简单应用1
- CountDownLatch和CyclicBarrier的应用场景
- CountDownLatch的使用方法和应用场景分析
- CountDownLatch和CyclicBarrier的应用场景
- JUC锁-09之 CountDownLatch原理和示例
- CountDownLatch 使用示例
- CountDownLatch使用示例
- Java并发之CountDownLatch的使用和源码解析
- 深度解析CountDownLatch源码
- CountDownLatch使用解析
- Java CountDownLatch应用
- CountDownLatch 与 CyclicBarrier应用
- Java CountDownLatch应用
- JUnit测试详解
- nyoj42一笔画问题
- Hibernate保存对象时,数据库出现乱码
- jmeter中使用jdbc参数化
- 动态规划--多重背包--hdu2844 coins
- CountDownLatch解析和应用示例
- jQuery 表单异步提交
- java web项目读取properties文件方法
- cocos动画编辑器导出动画在cocos中播放帧对不齐
- iOS 自定义对象数组去重
- 加载.properties文件的几种方式
- form表单提交时跳转到空白页面问题
- linux 服务器centos7系统lamp环境下安装redis
- 交叉验证(Cross Validation)方法思想简介