什么是CountDownLatch?
这是一种可以使得某个线程等待其他线程完成各自工作之后,同步执行的一个工具类。
原理:
通过一个计数器,初始值为所有线程的数量,当线程开启之后,数值减少1,当数值为0的时候,表示所有线程已经完成任务。
CountDownLatch如何工作
构造器中的计数值(count)实际上就是闭锁需要等待的线程数量。这个值只能被设置一次,而且CountDownLatch没有提供任何机制去重新设置这个计数值。
与CountDownLatch的第一次交互是主线程等待其他线程。主线程必须在启动其他线程后立即调用CountDownLatch.await()方法。这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务。
接下来举个demo来进行案例讲解:
package 并发编程12.CountDownLatch模块;
/**
* @author idea
* @data 2019/1/28
*/
public class Service {
public void testMethod() throws InterruptedException {
System.out.println(Thread.currentThread().getName()+"begin timer"+System.currentTimeMillis());
Thread.sleep((long) (Math.random()*1000));
System.out.println(Thread.currentThread().getName()+"end timer"+System.currentTimeMillis());
}
}
package 并发编程12.CountDownLatch模块;
import lombok.Data;
import java.util.concurrent.CountDownLatch;
/**
* @author idea
* @data 2019/1/28
*/
@Data
public class MyThread extends Thread {
private Service service;
private final CountDownLatch begin;
private final CountDownLatch end;
public MyThread(Service service, CountDownLatch begin, CountDownLatch end) {
this.service = service;
this.begin = begin;
this.end = end;
}
@Override
public void run() {
try {
begin.await(); //会堵塞当前线程 直到N变为0,如果该线程一直堵塞,不妨可以尝试一下await中加入相关时间参数来控制
// begin.await(2,TimeUnit.SECONDS);
service.testMethod();
} catch (InterruptedException e) {
e.printStackTrace();
}
end.countDown();
}
public Service getService() {
return service;
}
public MyThread setService(Service service) {
this.service = service;
return this;
}
public CountDownLatch getBegin() {
return begin;
}
public CountDownLatch getEnd() {
return end;
}
}
.
接下来是测试模块
package 并发编程12.CountDownLatch模块;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* @author idea
* @data 2019/1/28
*/
public class Test {
public static void main(String[] args) throws InterruptedException {
Service service=new Service();
CountDownLatch begin=new CountDownLatch(1);
//如果设置的countdownLatch过多,那么总线程就会一直不开始,如果数量过少,则只会对部分线程有效
CountDownLatch end=new CountDownLatch(10);
MyThread[] threadArray=new MyThread[10];
for(int i=0;i<10;i++){
threadArray[i]=new MyThread(service,begin,end);
threadArray[i].setName(i+"号选手");
threadArray[i].start();
}
System.out.println("等待裁判员开枪!"+System.currentTimeMillis());
long t1=System.currentTimeMillis();
//开始执行线程 堵塞主线程
begin.countDown();
//等待10个子线程执行完毕之后再执行,如果不想一直等待,可以设置时间
end.await(1,TimeUnit.MILLISECONDS);
System.out.println("比赛结束,时间为:"+System.currentTimeMillis());
}
}
CountDownLatch 类里面提供的主要方法有哪些?
CountDownLatch(int count)
void await()
boolean await(long timeout, TimeUnit unit)
void countDown()
long getCount()