Semaphore在此场景下控制并发的数量,lock加锁实现共享数据的互斥同步问题,这里模拟一家餐馆,有50主人和50和客人实现消费者生产者模式。控制同时只能有10个主人和10个客人来生产或者消费。
package cn.wzy.maintest;
import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Restaurant {
private Semaphore hosts = new Semaphore(10);
private Semaphore guests = new Semaphore(10);
private Lock lock = new ReentrantLock();
private Condition hostCondition = lock.newCondition();
private Condition guestCondition = lock.newCondition();
private Object[] cups;
private int size;
public Restaurant(int size) {
this.size = size;
cups = new Object[size];
for (int i = 0; i < size; ++i)
cups[i] = "a cup of water.";
}
private boolean IsFull() {
for (int i = 0; i < size; ++i) {
if (cups[i] == null) {
return false;
}
}
return true;
}
private boolean IsEmpty() {
for (int i = 0; i < size; ++i) {
if (cups[i] != null) {
return false;
}
}
return true;
}
public void create() {
try {
hosts.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.lock();
while (IsFull()) {
System.out.println(Thread.currentThread().getName() + "wait......");
try {
hostCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = 0; i < size; ++i) {
if (cups[i] == null) {
cups[i] = "a cup of water.";
System.out.println(Thread.currentThread().getName() + "create one");
break;
}
}
guestCondition.signalAll();
lock.unlock();
hosts.release();
}
public void receive() {
try {
guests.acquire();
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.lock();
while (IsEmpty()) {
System.out.println(Thread.currentThread().getName() + "wait......");
try {
guestCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = 0; i < size; ++i) {
if (cups[i] != null) {
cups[i] = null;
System.out.println(Thread.currentThread().getName() + "receive one");
break;
}
}
hostCondition.signalAll();
lock.unlock();
guests.release();
}
}
在create()方法中,每个线程执行一次都需要获取一个许可,同时可以10个主人线程进行生产,其中一个主人得到lock锁对象,当杯子的数量都是满的状态时,主人等待客人用完杯子,释放锁资源,直到有杯子空下来时,生产一杯水,唤醒等待喝水的客人,释放许可、锁资源。
在receive()方法中,同样,10个客人中只有一个客人得到lock锁,当杯子都是空的时候,等待生产,直到杯子不为空,接受水资源,唤醒等待生产的主人,释放许可、锁资源。
测试代码:
package cn.wzy.maintest;
public class Main {
public static void main(String[] args) {
Restaurant restaurant = new Restaurant(10);
Thread[] hosts = new Thread[50];
Thread[] guests = new Thread[50];
for (int i = 0; i < 50; ++i) {
hosts[i] = new Thread(() -> {
restaurant.create();
});
hosts[i].setName("host(" + i + ")");
hosts[i].start();
}
for (int i = 0; i < 50; ++i) {
guests[i] = new Thread(() -> {
restaurant.receive();
});
guests[i].setName("guest(" + i + ")");
guests[i].start();
}
}
}