CountDownLatch类位于java.util.concurrent包下,利用它可以实现类似计数器的功能。比如有一个任务A,它要等待其他4个任务执行完毕之后才能执行,此时就可以利用CountDownLatch来实现这种功能了。latch也即闭锁的意思,CountDownLatch是闭锁的一种实现,FutureTask也可以实现闭锁。
CountDownLatch类只提供了一个构造器:
public
CountDownLatch(
int
count) {...};
//参数count为计数值
public
void
await()
throws
InterruptedException { };
//等待直到count值为0才继续执行
public
boolean
await(
long
timeout, TimeUnit unit)
throws
InterruptedException { };
//和await()类似,只不过等待一定的时间后count值还没变为0的话就会继续执行
public
void
countDown() { };
//将count值减1
public
class
Test {
public
static
void
main(String[] args) {
final
CountDownLatch latch =
new
CountDownLatch(
2
);
new
Thread(){
public
void
run() {
try
{
System.out.println(
"子线程"
+Thread.currentThread().getName()+
"正在执行"
);
Thread.sleep(
3000
);
System.out.println(
"子线程"
+Thread.currentThread().getName()+
"执行完毕"
);
latch.countDown();
}
catch
(InterruptedException e) {
e.printStackTrace();
}
};
}.start();
new
Thread(){
public
void
run() {
try
{
System.out.println(
"子线程"
+Thread.currentThread().getName()+
"正在执行"
);
Thread.sleep(
3000
);
System.out.println(
"子线程"
+Thread.currentThread().getName()+
"执行完毕"
);
latch.countDown();
}
catch
(InterruptedException e) {
e.printStackTrace();
}
};
}.start();
try
{
System.out.println(
"等待2个子线程执行完毕..."
);
latch.await();
System.out.println(
"2个子线程已经执行完毕"
);
System.out.println(
"继续执行主线程"
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
}
}
CyclicBarrier字面意思回环栅栏(zha lan),通过它可以实现让一组线程等待至某个状态之后再全部同时执行。叫做回环是因为当所有等待线程都被释放以后,CyclicBarrier可以被重用。我们暂且把这个状态就叫做barrier,当调用await()方法之后,线程就处于barrier了。
CyclicBarrier类位于java.util.concurrent包下,CyclicBarrier提供2个构造器:
public
CyclicBarrier(
int
parties, Runnable barrierAction) {}
public
CyclicBarrier(
int
parties) {}
参数parties指让多少个线程或者任务等待至barrier状态;参数barrierAction为当这些线程都达到barrier状态时会执行的内容。
然后CyclicBarrier中最重要的方法就是await方法,它有2个重载版本:
public
int
await()
throws
InterruptedException, BrokenBarrierException { };
public
int
await(
long
timeout, TimeUnit unit)
throws
InterruptedException,BrokenBarrierException,TimeoutException { };
第一个版本比较常用,用来挂起当前线程,直至所有线程都到达barrier状态再同时执行后续任务;
第二个版本是让这些线程等待至一定的时间,如果还有线程没有到达barrier状态就直接让到达barrier的线程执行后续任务。
下面举几个例子就明白了:
假若有若干个线程都要进行写数据操作,并且只有所有线程都完成写数据操作之后,这些线程才能继续做后面的事情,此时就可以利用CyclicBarrier了:
public
class
Test {
public
static
void
main(String[] args) {
int
N =
4
;
CyclicBarrier barrier =
new
CyclicBarrier(N);
for
(
int
i=
0
;i<N;i++)
new
Writer(barrier).start();
}
static
class
Writer
extends
Thread{
private
CyclicBarrier cyclicBarrier;
public
Writer(CyclicBarrier cyclicBarrier) {
this
.cyclicBarrier = cyclicBarrier;
}
@Override
public
void
run() {
System.out.println(
"线程"
+Thread.currentThread().getName()+
"正在写入数据..."
);
try
{
Thread.sleep(
5000
);
//以睡眠来模拟写入数据操作
System.out.println(
"线程"
+Thread.currentThread().getName()+
"写入数据完毕,等待其他线程写入完毕"
);
cyclicBarrier.await();
}
catch
(InterruptedException e) {
e.printStackTrace();
}
catch
(BrokenBarrierException e){
e.printStackTrace();
}
System.out.println(
"所有线程写入完毕,继续处理其他任务..."
);
}
}
}
public
class
Test {
public
static
void
main(String[] args) {
int
N =
4
;
CyclicBarrier barrier =
new
CyclicBarrier(N,
new
Runnable() {
@Override
public
void
run() {
System.out.println(
"当前线程"
+ Thread.currentThread().getName());
try
{
Thread.sleep(
10000
);
}
catch
(InterruptedException e) {}
System.out.println(
"额外任务完成"
);
}
});
for
(
int
i =
0
; i < N; i++)
new
Writer(barrier).start();
}
static
class
Writer
extends
Thread {
private
CyclicBarrier cyclicBarrier;
public
Writer(CyclicBarrier cyclicBarrier) {
this
.cyclicBarrier = cyclicBarrier;
}
@Override
public
void
run() {
System.out.println(
"线程"
+ Thread.currentThread().getName()+
"正在写入数据..."
);
try
{
Thread.sleep(
2000
);
// 以睡眠来模拟写入数据操作
System.out.println(
"线程"
+ Thread.currentThread().getName()+
"写入数据完毕,等待其他线程写入完毕"
);
/*如果有额外任务,当满足往下执行条件时,会先从在该处等待的线程中随机选出一个来执行额外任务,其它线程继续阻塞,
* 知道额外任务结束,所有线程(包括执行额外任务的线程)才可以往下执行
*/
cyclicBarrier.await();
System.out.println(
"所有线程写入完毕,继续处理其他任务..."
);
Thread.sleep(
3000
);
System.out.println(
"线程"
+Thread.currentThread().getName()+
"结束"
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
catch
(BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
public
class
Test {
public
static
void
main(String[] args) {
int
N =
4
;
CyclicBarrier barrier =
new
CyclicBarrier(N);
for
(
int
i =
0
; i < N +
2
; i++) {
new
Writer(barrier).start();
}
try
{
Thread.sleep(
25000
);
}
catch
(InterruptedException e) {
e.printStackTrace();
}
System.out.println(
"CyclicBarrier重用"
);
for
(
int
i =
0
; i < N +
2
; i++) {
new
Writer(barrier).start();
}
}
static
class
Writer
extends
Thread {
private
CyclicBarrier cyclicBarrier;
public
Writer(CyclicBarrier cyclicBarrier) {
this
.cyclicBarrier = cyclicBarrier;
}
@Override
public
void
run() {
System.out.println(
"线程"
+ Thread.currentThread().getName() +
"正在写入数据..."
);
try
{
Thread.sleep(
5000
);
// 以睡眠来模拟写入数据操作
System.out.println(
"线程"
+ Thread.currentThread().getName() +
"写入数据完毕,等待其他线程写入完毕"
);
cyclicBarrier.await();
}
catch
(InterruptedException e) {
e.printStackTrace();
}
catch
(BrokenBarrierException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() +
"所有线程写入完毕,继续处理其他任务..."
);
}
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。