Semaphore+lock实现生产者消费者模式

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

猜你喜欢

转载自blog.csdn.net/qq_38089964/article/details/80803243
今日推荐