Java concurrent包中有提供多种同步器,信号量(Semaphore)、计数栓(CountDownLatch)、循环屏障(CyclicBarrier)、交换器(Exchanger)、Phaser
一、 Semaphore同步器
特征:
1. 经典的信号量,通过计数器控制对共享资源的访问
2. Semaphore(int count):创建拥有count个许可证的信号量
3.acquire()/acquire(int num) : 获取1/num个许可证
4. release/release(int num) : 释放1/num个许可证
用以下代码模拟该编程模型!
package com.concurrent.src;
import java.util.concurrent.Semaphore;
/**
* 信号量编程模型(三个客户去柜台办事,只初始化两个窗口,当有窗口闲下来才能为第三个客户服务)
* @author admin
*
*/
public class Ademo {
public static void main(String[] args) {
// 初始化两个银行柜员(窗口)
Semaphore semaphore = new Semaphore(2);
// 有A,B,C三个客户
Person p1 = new Person(semaphore,"A");
p1.start();
Person p2 = new Person(semaphore,"B");
p2.start();
Person p3 = new Person(semaphore,"C");
p3.start();
}
}
class Person extends Thread {
private Semaphore semaphore;
public Person(Semaphore semaphore,String name) {
setName(name);
this.semaphore = semaphore;
}
@Override
public void run() {
System.out.println(getName() + " is waiting....");
try {
// 获取许可证
semaphore.acquire();
System.out.println(getName() + " is servicing ....");
// 休眠一秒
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(getName() + " is done!");
// 释放信号量
semaphore.release();
}
}
执行结果:
B is waiting....
B is servicing ....
A is waiting....
A is servicing ....
C is waiting....
B is done!
C is servicing ....
A is done!
C is done!
二、 CountDownLatch同步器
特征:
1. 必须发生指定数量的事件后才可以继续运行(比如赛跑比赛,裁判喊出3,2,1之后大家才同时跑)
2. CountDownLatch(int count):必须发生count个数量才可以打开锁存器
3. await:等待锁存器
4. countDown:触发事件
以下为计数栓编程模型:
package com.concurrent.src;
import java.util.concurrent.CountDownLatch;
/**
* 数三个数同时起跑
* @author admin
*
*/
public class Bdemo {
public static void main(String[] args) {
// 创建一个计算栓,数三个数
CountDownLatch countDownLatch = new CountDownLatch(3);
// 有A,B,C个运动员
new Racer(countDownLatch, "A").start();
new Racer(countDownLatch, "B").start();
new Racer(countDownLatch, "C").start();
// 倒计时
for (int i = 0; i < 3; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(3-i);
// 倒计时触发事件 -1
countDownLatch.countDown();
if(i == 2) {
System.out.println("start.....");
}
}
}
}
class Racer extends Thread {
private CountDownLatch countDownLatch;
public Racer(CountDownLatch countDownLatch,String name) {
setName(name);
this.countDownLatch = countDownLatch;
}
@Override
public void run() {
System.out.println(getName() + " is waiting....");
try {
// 等待锁存器
countDownLatch.await();;
for (int i = 0; i < 3; i++) {
System.out.println(getName() + " : " + i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
A is waiting....
C is waiting....
B is waiting....
3
2
1
start.....
A : 0
A : 1
A : 2
C : 0
C : 1
C : 2
B : 0
B : 1
B : 2
三、CyclicBarrier同步器
特征:
1. 适用于只有多个线程都到达预定点时才可以继续执行(比如斗地主,需要等齐三个人才开始)
2. CyclicBarrier(int num) :等待线程的数量
3. CyclicBarrier(int num, Runnable action) :等待线程的数量以及所有线程到达后的操作
4. await() : 到达临界点后暂停线程
以下代码模拟该模型:
package com.concurrent.src;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
/**
* 斗地主:需要等待齐三个玩家游戏才开始
* @author admin
*
*/
public class Cdemo {
public static void main(String[] args) {
// 创建循环屏障,条件满足时就执行runnable
CyclicBarrier cyclicBarrier = new CyclicBarrier(3, new Runnable() {
@Override
public void run() {
System.out.println("Game start...");
}
});
// 有A,B,C三个玩家
new Player(cyclicBarrier, "A").start();
new Player(cyclicBarrier, "B").start();
new Player(cyclicBarrier, "C").start();
}
}
class Player extends Thread {
private CyclicBarrier cyclicBarrier;
public Player(CyclicBarrier cyclicBarrier,String name) {
setName(name);
this.cyclicBarrier = cyclicBarrier;
}
@Override
public void run() {
System.out.println(getName() + " is waiting other player....");
try {
// 屏障处等待
cyclicBarrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}
执行结果:
A is waiting other player....
C is waiting other player....
B is waiting other player....
Game start...
此处模拟略!暂时没用到!
五、Phaser同步器
特征:
1. 工作方式与CyclicBarrier类似,但是可以定义多个阶段
2. Phaser()/Phaser(int num) : 使用指定0/num个party创建Phaser
3. register() : 注册party
4. arriveAndAdvance() : 到达时等待到所有party到达
5. arriveAndDeregister() : 到达时注销线程自己
以下代码模拟该同步器:
package com.concurrent.src;
import java.util.concurrent.Phaser;
/**
* 一个一个订单处理
* @author admin
*
*/
public class Ddemo {
public static void main(String[] args) {
Phaser phaser = new Phaser(1);
System.out.println("starting...");
// 点餐用餐中会包含多个人员服务
new Worker(phaser, "服务员").start();
new Worker(phaser, "打荷员").start();
new Worker(phaser, "厨师").start();
for (int i = 1; i <= 3; i++) {
phaser.arriveAndAwaitAdvance();
System.out.println("Order " + i + " finished");
}
// 注销
phaser.arriveAndDeregister();
System.out.println("Order all done ");
}
}
class Worker extends Thread {
private Phaser phaser;
public Worker(Phaser phaser,String name) {
setName(name);
this.phaser = phaser;
}
@Override
public void run() {
for (int i = 1; i <= 3; i++) {
System.out.println( "current order is : " + i + " : " + getName());
if (i == 3) {
phaser.arriveAndDeregister();
} else {
phaser.arriveAndAwaitAdvance();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
starting...
Order 1 finished
Order 2 finished
Order 3 finished
Order all done
current order is : 1 : 打荷员
current order is : 1 : 服务员
current order is : 1 : 厨师
current order is : 2 : 打荷员
current order is : 2 : 服务员
current order is : 2 : 厨师
current order is : 3 : 打荷员
current order is : 3 : 服务员
current order is : 3 : 厨师