目录
Phaser
Semaphore
CyclicWorker
CountDownLatch
类似于旅行团集合后到景点旅游
import java.util.Random;
import java.util.concurrent.Phaser;
public class Lesson5_6 {
public static void main(String[] args) throws InterruptedException {
Phaser phaser = new MyPhaser();
//登记有几个人
PhaserWorker[] phaserWorkers = new PhaserWorker[10];
for (int i = 0; i < phaserWorkers.length; i++) {
phaserWorkers[i] = new PhaserWorker(phaser);
// 注册 Phaser 等待的线程数,执行一次等待线程数 +1
int register = phaser.register();
System.out.println("登记:"+i);
// register = phaser.arrive();
// System.out.println("register:"+register);
}
//创造旅客,多于登记个数报异常,继续执行,并抛弃多于的那一个,少于登记个数,会一直阻塞
for (int i = 0; i < phaserWorkers.length; i++) {
// 执行任务
new Thread(new PhaserWorker(phaser)).start();
System.out.println("create");
}
}
static class PhaserWorker implements Runnable {
private final Phaser phaser;
public PhaserWorker(Phaser phaser) {
this.phaser = phaser;
}
@Override
public void run() {
//表示所有线程暂停在这一步,等到所有线程都到了(10个)再继续向下(多于10,报异常,并抛弃多于的那个,少于10个,会一直阻塞在这里)
int login = phaser.arriveAndAwaitAdvance();
System.out.println(Thread.currentThread().getName() + " | 到达::景点"+ login );
try {
Thread.sleep(new Random().nextInt(5) * 1000);
login = phaser.arriveAndAwaitAdvance();
System.out.println(Thread.currentThread().getName() + " | 到达 ::景点"+login );
//phaser.arriveAndAwaitAdvance(); // 景点 1 集合完毕发车
Thread.sleep(new Random().nextInt(5) * 1000);
login = phaser.arriveAndAwaitAdvance();
System.out.println(Thread.currentThread().getName() + " | 到达::景点"+login );
//phaser.arriveAndAwaitAdvance(); // 景点 2 集合完毕发车
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
// Phaser 每个阶段完成之后的事件通知
static class MyPhaser extends Phaser{
@Override
protected boolean onAdvance(int phase, int registeredParties) { // 每个阶段执行完之后的回调
switch (phase) {
case 0:
System.out.println("==== 集合完毕发车 ====");
return false;
case 1:
System.out.println("==== 景点1集合完毕,发车去下一个景点 ====");
return false;
case 2:
System.out.println("==== 景点2集合完毕,发车回家 ====");
return false;
default:
return true;
}
}
}
}
类似于车库里面车位,本例车位5个,车有十个,每辆车出库时间随机
import java.time.LocalDateTime;
import java.util.Random;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class semaphore {
public static void main(String[] args) {
//相当于车位,本例5个
Semaphore semaphore = new Semaphore(5);
ThreadPoolExecutor semaphoreThread = new ThreadPoolExecutor(10, 50, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
for (int i = 0; i < 10; i++) {
semaphoreThread.execute(() -> {
try {
// 堵塞获取许可,车子入库
semaphore.acquire();
System.out.println("Thread:" + Thread.currentThread().getName() + " 时间:" + LocalDateTime.now());
long time = 1000L*(new Random().nextInt(7)+3);
TimeUnit.SECONDS.sleep(time/1000);
// 释放许可,车子出库
semaphore.release();
//队列长度表示未入库车辆个数
int length = semaphore.getQueueLength();
System.out.println("队列长度"+length);
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
}
}
}
类似于大巴车,一次只运送一定数量乘客
import java.util.Random;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class CyclicBarrierTest {
public static void main(String[] args) throws InterruptedException {
AtomicInteger count = new AtomicInteger();
CyclicBarrier cyclicBarrier = new CyclicBarrier(4, new Runnable() {
@Override
public void run() {
System.out.println("发车了,当前车次:"+count.getAndIncrement());
//System.out.println("首位乘客:"+Thread.currentThread().getName());
}
});
//一共10个乘客,只拉两次
System.out.println("全部乘客:");
for (int i = 0; i < 20; i++) {
new Thread(new CyclicWorker(cyclicBarrier)).start();
}
}
static class CyclicWorker implements Runnable {
private CyclicBarrier cyclicBarrier;
CyclicWorker(CyclicBarrier cyclicBarrier) {
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
long time = 1000L*(new Random().nextInt(7)+3);
System.out.println("当前乘客:"+Thread.currentThread().getName());
try {
Thread.sleep(time);
//等待,执行一次表示出现一名乘客
cyclicBarrier.await();
System.out.println("上车乘客:"+Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
}
相当于医院患者早到排队,医生诊治的模型
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class JUC {
public static void main(String[] args) throws InterruptedException {
// 医院闭锁
CountDownLatch hospitalLatch = new CountDownLatch(1);
int patient = 10;
// 患者闭锁
CountDownLatch patientLatch = new CountDownLatch(patient);
System.out.println("患者排队");
//此处采用缓存线程池,表示医院医生很多,能满足一对一体检,此处有patient个人排队
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < patient; i++) {
final int j = i;
executorService.execute(() -> {
long time = 1000L*(new Random().nextInt(10)+1);
try {
//表示可以开始接受另外一个队列
//当计数器不为 0 时,则调用该方法的线程阻塞,当计数器为 0 时,可以唤醒等待的一个或者全部线程
//(此处现在是0,即可以唤起10个线程)
hospitalLatch.await();
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" 体检:" + j+" 耗时:"+time/1000);
patientLatch.countDown();
});
}
System.out.println("医生上班");
hospitalLatch.countDown();
//表示患者队列不再增加
//当计数器不为 0 时,则调用该方法的线程阻塞,当计数器为 0 时,可以唤醒等待的一个或者全部线程
//此处现在不是0,即此方法的线程阻塞,一直到patientLatch.countDown()降低到0为止
patientLatch.await();
//程序阻塞结束,开始执行下一步
System.out.println("医生下班");
executorService.shutdown();
}
}