这是继许上一篇java 使用synchronized, wait(), notifyAll() 实现生产者-消费者模式。
信号量Semaphore,跟交通信号等非常类似(Semaphore翻译过来就是信号灯的意思),以下面这幅图为例
如果两条铁轨都是空的,那么此时信号灯是绿色(信号量为2),允许火车通行。如果有列车请求通行则放行,同时信号灯变为黄色(信号量减一):
当两条铁轨都有列车通行时,信号灯为红色(信号量为0),不允许火车通过。若果有列车请通行则阻塞:
当一辆列车离开铁轨的后,信号灯变为黄色(信号量为1),此时等待的通行的列车被放行:
有了上面的感性认识后,我们来看看到底如何表示信号量。
可定用一个整数表示信号量,然后有一个增加操作和一个减少操作,于是有如下的
class Semaphore{
private volatile int permit;
public Semaphore(int permit){
this.permit = permit;
}
public acquire(){
if (permit <= 0){
//等待
}
//执行permit--操作
}
public release(){
//执行permit++ 操作
if(permit > 0){
//唤醒
}
}
}
- 这里有两点需要说明:
- 这里先用一个二进制信号量来等效互斥操作;
- 由于信号量只能通过0值来进行阻塞和唤醒,所以这里必须使用两个信号量来模拟容器空和容器满两种状态
public class Cache {
private int cacheSize = 0;
public Semaphore mutex;
public Semaphore empty; //保证了容器空的时候(empty的信号量<=0), 消费者等待
public Semaphore full; //保证了容器满的时候(full的信号量 <= 0),生产者等待
public Cache(int size) {
mutex = new Semaphore(1); //二进制信号量,表示互斥锁
empty = new Semaphore(size);
full = new Semaphore(0);
}
public int getCacheSize()throws InterruptedException{
return cacheSize;
}
public void produce() throws InterruptedException{
empty.acquire(); // 消耗一个空位
mutex.acquire();
cacheSize++;
System.out.println("生产了一个产品, 当前产品数为" + cacheSize);
mutex.release();
full.release(); // 增加了一个产品
}
public void consume() throws InterruptedException{
full.acquire(); // 消耗了一个产品
mutex.acquire();
cacheSize--;
System.out.println("消费了一个产品, 当前产品数为" + cacheSize);
mutex.release();
empty.release(); // 增加了一个空位
}
}
public class Consumer implements Runnable {
private Cache cache;
public Consumer(Cache cache){
this.cache = cache;
}
@Override
public void run() {
while(true){
try {
cache.consume();
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Producer implements Runnable {
private Cache cache;
public Producer(Cache cache){
this.cache = cache;
}
@Override
public void run() {
while(true){
try {
cache.produce();
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class Main {
public static void main(String[] args) {
Cache cache = new Cache(10);
Producer p = new Producer(cache);
Consumer c = new Consumer(cache);
int producerCount = 4, consumerCount = 4;
for (int i = 0; i < producerCount; i++){
new Thread(p).start();
}
for (int i = 0; i < consumerCount; i++){
new Thread(c).start();
}
}
}
未完待续。。。(下一篇:通过管程(Monitor)来实现生产者-消费者模式)