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();}}
}