您的位置:首页 > 编程语言 > Java开发

java多线程-concurrent-CountDownLatch和CyclicBarrier

2016-07-24 00:00 543 查看
摘要: CountDownLatch和CyclicBarrier都可以控制多个相关线程按照一定规则的运行,CountDownLatch是其它线程都”做了某事“后“主线程”执行某操作,CyclicBarrier的不同是先到达某状态的线程会wait其他线程。

CountDownLatch

import java.util.concurrent.CountDownLatch;

public class CountDownLatchTest {

private static final int N = 5;

public static void main(String[] args) throws InterruptedException {
CountDownLatch doneSignal = new CountDownLatch(N);
CountDownLatch startSignal = new CountDownLatch(1);// 开始执行信号

for (int i = 1; i <= N; i++) {
new Thread(new Worker(i, doneSignal, startSignal)).start();// 启动线程,run里面开始是一个wait,会阻塞
}
System.out.println("main() begin------------");
startSignal.countDown();// 其他线程都在wait,这时wait不再阻塞,全部开始工作
doneSignal.await();// 主线程阻塞,等待所有的线程执行完毕
System.out.println("main() Ok");

}

/**
* 必须引用闭锁对象,因为他们需要通知CountDownLatch对象,他们已经完成了各自的任务。这种通知机制是通过
* CountDownLatch.countDown()方法来完成的;每调用一次这个方法,在构造函数中初始化的count值就减1。所以当N个线程都调
* 用了这个方法,count的值等于0,然后主线程就能通过await()方法,恢复执行自己的任务。
*
* @author 刘杰
* @time 2016年7月24日 下午4:27:46
*/
static class Worker implements Runnable {
private final CountDownLatch doneSignal;
private final CountDownLatch startSignal;
private int beginIndex;

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

public void run() {
try {
startSignal.await(); // 等待开始执行信号的发布
beginIndex = (beginIndex - 1) * 10 + 1;
for (int i = beginIndex; i < beginIndex + 10; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
System.out.println(Thread.currentThread().getName() + ":我说完咯");
doneSignal.countDown();// 已经完成,计数减一
System.out.println(Thread.currentThread().getName() + ":bye~");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

输出:

main() begin------------
Thread-2:21
Thread-0:1
Thread-3:31
Thread-1:11
Thread-4:41
Thread-1:12
Thread-1:13
Thread-1:14
Thread-1:15
Thread-1:16
Thread-3:32
Thread-0:2
Thread-2:22
Thread-0:3
Thread-3:33
Thread-1:17
Thread-4:42
Thread-1:18
Thread-3:34
Thread-0:4
Thread-2:23
Thread-0:5
Thread-3:35
Thread-1:19
Thread-4:43
Thread-1:20
Thread-3:36
Thread-0:6
Thread-2:24
Thread-0:7
Thread-3:37
Thread-1:我说完咯
Thread-4:44
Thread-1:bye~
Thread-3:38
Thread-3:39
Thread-0:8
Thread-2:25
Thread-0:9
Thread-3:40
Thread-4:45
Thread-3:我说完咯
Thread-0:10
Thread-2:26
Thread-0:我说完咯
Thread-3:bye~
Thread-4:46
Thread-4:47
Thread-0:bye~
Thread-2:27
Thread-4:48
Thread-2:28
Thread-4:49
Thread-2:29
Thread-4:50
Thread-2:30
Thread-4:我说完咯
Thread-2:我说完咯
Thread-4:bye~
main() Ok
Thread-2:bye~

CyclicBarrier

import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CyclicBarrierTest {

public static void main(String[] args) {
ExecutorService exec = Executors.newCachedThreadPool();
final Random random = new Random();

final CyclicBarrier barrier = new CyclicBarrier(4, new Runnable() {
@Override
public void run() {
System.out.println("大家都到齐了,开始happy去");
}
});

for (int i = 0; i < 4; i++) {
exec.execute(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(random.nextInt(1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":我到了");
try {
barrier.await();// 等待其他哥们
System.out.println(Thread.currentThread().getName() + ":走起!");
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
});
}
exec.shutdown();
}

}

输出:

pool-1-thread-3:我到了
pool-1-thread-4:我到了
pool-1-thread-2:我到了
pool-1-thread-1:我到了
大家都到齐了,开始happy去
pool-1-thread-1:走起!
pool-1-thread-3:走起!
pool-1-thread-4:走起!
pool-1-thread-2:走起!


总结:

CyclicBarrier就是一个栅栏,等待所有线程到达后再执行相关的操作;

barrier 在释放等待线程后可以重用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息