latch java_Java并发工具类 - CountDownLatch

Java并发工具类 - CountDownLatch

1、简介

CountDownLatch能够使一个或多个线程等待其他线程完成各自的工作后再执行;CountDownLatch是JDK 5+里面闭锁的一个实现。

闭锁(Latch):一种同步方法,可以延迟线程的进度直到线程到达某个终点状态。通俗的讲就是,一个闭锁相当于一扇大门,在大门打开之前所有线程都被阻断,一旦大门打开所有线程都将通过,但是一旦大门打开,所有线程都通过了,那么这个闭锁的状态就失效了,门的状态也就不能变了,只能是打开状态。也就是说闭锁的状态是一次性的,它确保在闭锁打开之前所有特定的活动都需要在闭锁打开之后才能完成。

与CountDownLatch第一次交互是主线程等待其它的线程,主线程必须在启动其它线程后立即调用await方法,这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务。

其他的N个线程必须引用闭锁对象,因为他们需要通知CountDownLatch对象,他们已经完成了各自的任务,这种机制就是通过countDown()方法来完成的。每调用一次这个方法,在构造函数中初始化的count值就减1,所以当N个线程都调用了这个方法count的值等于0,然后主线程就能通过await方法,恢复自己的任务。

这里的主线程是相对的概念,需要根据CountDownLatch创建的场景分析。

2、主要方法

特有方法:public CountDownLatch(int count); //指定计数的次数,只能被设置1次

public void countDown(); //调用此方法则计数减1

public void await() throws InterruptedException //调用此方法会一直阻塞当前线程,直到计时器的值为0,除非线程被中断。

Public Long getCount(); //得到当前的计数

Public boolean await(long timeout, TimeUnit unit) //调用此方法会一直阻塞当前线程,直到计时器的值为0,除非线程被中断或者计数器超时,返回false代表计数器超时。

From Object Inherited:

Clone、equals、hashCode、notify、notifyALL、wait等。

3、使用场景

(1)开启多个线程分块下载一个大文件,每个线程只下载固定的一截,最后由另外一个线程来拼接所有的分段。

(2)应用程序的主线程希望在负责启动框架服务的线程已经启动所有的框架服务之后再执行。

(3)确保一个计算不会执行,直到所需要的资源被初始化。

......

4、参考例子

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classCountDownLatchDemo {final static SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");public static void main(String[] args) throwsInterruptedException {

CountDownLatch latch=new CountDownLatch(2);//两个工人的协作

Worker worker1=new Worker("zhang san", 5000, latch);

Worker worker2=new Worker("li si", 8000, latch);

worker1.start();//

worker2.start();//

latch.await();//等待所有工人完成工作

System.out.println("all work done at "+sdf.format(newDate()));

}static class Worker extendsThread{

String workerName;intworkTime;

CountDownLatch latch;public Worker(String workerName ,intworkTime ,CountDownLatch latch){this.workerName=workerName;this.workTime=workTime;this.latch=latch;

}public voidrun(){

System.out.println("Worker "+workerName+" do work begin at "+sdf.format(newDate()));

doWork();//工作了

System.out.println("Worker "+workerName+" do work complete at "+sdf.format(newDate()));

latch.countDown();//工人完成工作,计数器减一

}private voiddoWork(){try{

Thread.sleep(workTime);

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}

View Code

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

class Driver { //...

void main() throwsInterruptedException {

CountDownLatch startSignal= new CountDownLatch(1);

CountDownLatch doneSignal= newCountDownLatch(N);for (int i = 0; i < N; ++i) //create and start threads

new Thread(newWorker(startSignal, doneSignal)).start();

doSomethingElse();//don't let run yet

startSignal.countDown(); //let all threads proceed

doSomethingElse();

doneSignal.await();//wait for all to finish

}

}class Worker implementsRunnable {private finalCountDownLatch startSignal;private finalCountDownLatch doneSignal;

Worker(CountDownLatch startSignal, CountDownLatch doneSignal) {this.startSignal =startSignal;this.doneSignal =doneSignal;

}public voidrun() {try{

startSignal.await();

doWork();

doneSignal.countDown();

}catch (InterruptedException ex) {} //return;

}voiddoWork() { ... }

}

View Code

注:

1. latch.countDown(); 建议放到finally语句里。

2. 对这个计数器的操作都是原子操作,同时只能有一个线程去操作这个计数器。

5、常见面试题

通过上述的介绍很容易解决下面的面试题:

(1)解释一下CountDownLatch概念?

(2)CountDownLatch 和CyclicBarrier的不同之处?

(3)给出一些CountDownLatch使用的例子?

(4) CountDownLatch 类中主要的方法?

6、参考资料

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值