最近几篇文章都是关于线程的,本篇文章也同样是关于线程的。
工作中,肯定少不了公司开会这一步骤;而开会时也需要等到开会人员全部到场后会议才能开始,这时候我们该如何实现呢?当然是使用Java API中的CountDownLatch线程同步辅助类
了。
1.CountDownLatch介绍
使用CountDownLatch辅助类,调用
await()
后可以让线程等待其他线程完成一组操作/步骤后继续进行,否则就一直处于等待状态;它内部自带一个计数器(构造函数中初始化),当其他线程调用countDown()
时内部计数器减一直到0时,等待的线程继续执行。
我们来看一下它的构造函数以及常用的方法:
构造函数:
/**
* Constructs a {@code CountDownLatch} initialized with the given count.
*
* @param count the number of times {@link #countDown} must be invoked
* before threads can pass through {@link #await}
* @throws IllegalArgumentException if {@code count} is negative
*/
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
构造函数中的count就是其内部维护的计数器的初始值。
await()
: 使的当前线程进入等待状态直到内部计数器的值为0后继续执行
countDown()
:使内部计数器值减一
getCount()
:获取内部计数器值
2.CountDownLatch使用
案例: 模拟开会过程,等待所有人员到达后才开始开会。
**开会线程类:**内部持有一个CountDownLatch线程辅助类,run方法中调用await进入等待状态。带有参会人员到达类,调用countDown()方法。
package countDownLatch;
import java.util.concurrent.CountDownLatch;
//会议类
public class Meeting implements Runnable {
private CountDownLatch downLatch;
public Meeting(int numberOfThreadWaiting) {
downLatch = new CountDownLatch(numberOfThreadWaiting);
}
@Override
public void run() {
System.out.println("Meeting initialization....");
try {
downLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("All arrived,Meeting start...");
}
public void arrive(String name) {
System.out.println(name + " arrived");
downLatch.countDown();
System.out.printf("%s people still have to wait?\n", downLatch.getCount());
}
}
参会人员类:内部持有开会类的引用,随机时间到达,到达后调用开会类中的到达方法。
package countDownLatch;
import java.util.concurrent.TimeUnit;
//参会人员
public class Participant implements Runnable {
private Meeting meeting;
private String name;
public Participant(Meeting meeting, String name) {
this.meeting = meeting;
this.name = name;
}
@Override
public void run() {
long duration = (long) (Math.random() * 30);
try {
TimeUnit.SECONDS.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
meeting.arrive(this.name);
}
}
使用:
Meeting meeting = new Meeting(10);
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(meeting);
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new Participant(meeting,"thread "+i));
thread.start();
}
案例输出:
Meeting initialization....
thread 4 arrived
9 people still have to wait?
thread 6 arrived
8 people still have to wait?
thread 5 arrived
7 people still have to wait?
thread 0 arrived
6 people still have to wait?
thread 7 arrived
5 people still have to wait?
thread 3 arrived
4 people still have to wait?
thread 2 arrived
3 people still have to wait?
thread 8 arrived
2 people still have to wait?
thread 9 arrived
1 people still have to wait?
thread 1 arrived
0 people still have to wait?
All arrived,Meeting start...