面对大并发场景下,偶尔会出现排队调度相关情况,在Java中有几个比较常见的调度模式,本文将分享这些调度模式:
- CountDownLatch倒计时门栓
- CyclicBarrier障栅
- Semamphore信号量
- Phaser循环障栅
Part-1:CountDownLatch倒计时门栓
用来同步一个或多个任务,强制它们等待由其它任务执行的一组操作完成。门栓是一次性的当计数器为0的时候就不能再重用了。
public class StudyCountDownLatch {
private final int wait_count = 100;
private final int work_count = 100;
private final int count_down_latch_count = 100;
private final CountDownLatch countDownLatch = new CountDownLatch(count_down_latch_count);
public class DoWork implements Runnable {
@Override
public void run() {
for (int i = 0; i < 2; i++) {
try {
Thread.currentThread().join(1000);
System.out.println(Thread.currentThread().getName() + "第" + i + "次获取任务");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
countDownLatch.countDown();
System.out.println(Thread.currentThread().getName() + "任务完成,任务数:" + countDownLatch.getCount());
}
}
public class WaitSomeTime implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "任务等待--开始");
try {
countDownLatch.await(1, TimeUnit.SECONDS);
System.out.println(Thread.currentThread().getName() + "任务等待--结束");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Test
public void testCountDownLatch() throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < wait_count; i++) {
executorService.execute(new WaitSomeTime());
}
for (int i = 0; i < work_count; i++) {
executorService.execute(new DoWork());
}
Thread.sleep(100000);
}
}
Part-2:CyclicBarrier障栅
同步方式类似于排队游乐场过山车,满员或超过指定时间就服务。类似创建一个集结点,当任务到达集结点就停止,等所有任务都到达集结点障栅就撤销,线程就可以继续工作了
public class StudyCyclicBarrier {
private final CyclicBarrier cyclicBarrier = new CyclicBarrier(3);
class DoWork implements Runnable {
private CyclicBarrier cyclicBarrier;
public DoWork(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName()+"输出--开始"
+"等待数量:"+cyclicBarrier.getNumberWaiting()
);
this.cyclicBarrier.await();
System.out.println(Thread.currentThread().getName()+"输出--结束"
+"等待数量:"+cyclicBarrier.getNumberWaiting());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
@Test
public void testCyclicBarrier(){
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 11; i++) {
executorService.execute(new DoWork(cyclicBarrier));
}
}
}
Part-3:Semaphore信号量
该机制类似参观机制,限定单位容量参观数量,只有拿到信号卡的人才能参观,当参观卡被人拿完只能等待其它人参观完了后释放参观卡才能进入。
一般这个机制在软件项目中,下游系统单位时间响应能力有限,就需要通过该机制进行限流。
public class StudySemaphore {
private final Semaphore semaphore = new Semaphore(3, true);
class DoWork implements Runnable {
private String workName;
public DoWork(String workName) {
this.workName = workName;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "任务{" + workName + "}结束");
try {
Thread.currentThread().join(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
semaphore.release();
}
}
@Test
public void testSemaphore() throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 11; i++) {
semaphore.acquire();
executorService.execute(new StudySemaphore.DoWork(String.valueOf(i)));
}
}
}
Part-4:Phaser循环障栅
class RunGame implements Runnable {
private Phaser phaser;
private String runnerCode;
public RunGame(String runnerCode, Phaser phaser) {
this.phaser = phaser;
this.runnerCode = runnerCode;
}
@Override
public void run() {
try {
int wait_time = new Random().nextInt(4) * 1000;
System.out.println(runnerCode + "选手入场-等待"+wait_time);
Thread.sleep(wait_time);
phaser.arriveAndAwaitAdvance();//到达障栅,等待其它任务到达
System.out.println(runnerCode + "选手等待信号" + wait_time);
Thread.sleep(wait_time);
phaser.arriveAndAwaitAdvance();//到达障栅,等待其它任务到达
wait_time = new Random().nextInt(4) * 1000;
Thread.sleep(wait_time);
System.out.println(runnerCode + "选手到达终点" + wait_time);
phaser.arriveAndDeregister();//到达障栅,注销障栅
Thread.sleep(wait_time);
System.out.println(runnerCode+"离开场地");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Test
public void testPhaser_02() throws InterruptedException {
ExecutorService executorService = Executors.newCachedThreadPool();
Phaser phaser = new Phaser();
for (int i = 0; i < 5; i++) {
phaser.register();//注册障栅,相当于增加数量1
executorService.execute(new RunGame(String.valueOf(i), phaser));
}
while(!phaser.isTerminated()){
Thread.sleep(100);
}
System.out.println("game over");
}
参考文档
Java编程思想-第四版
更多文章请关注公众号:技术研究与团队管理(TR_TM_Lehman)