Java 并发编程学习笔记(5) ----Semaphore-使用Semaphore 实现一个多生产者/消费者

多生产者/消费者

多个生产者和消费者,同时限制生产者和消费者的数量
类Semaphore提供了限制并发线程数的功能,此功能在默认的synchronized中是不提供的。

代码


/**
 * 实现生产者消费者模式
 * 限制生产者与消费者的数量
 */
package com.lhc.concurrent.semaphore.repast;

import java.util.concurrent.Semaphore;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class RepastService {
    /**
     * 初始化生产者和消费者两个信号量
     */
    volatile private Semaphore cook = new Semaphore(10);
    volatile private Semaphore diner = new Semaphore(5);
    /**
     * 初始化两个Condition
     */
    volatile private ReentrantLock lock = new ReentrantLock();
    volatile private Condition setCondition = lock.newCondition();
    volatile private Condition getCondition = lock.newCondition();
    /**
     * 初始化一个容器
     */
    volatile private Object[] producePosition = new Object[4];

    /**
     * 判断容器是否为空
     * @return
     */
    public boolean isEmpty() {
        for (int i = 0; i < producePosition.length; i++) {
            if (producePosition[i] != null) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断容器是否已满
     * @return
     */
    public boolean isFull() {
        for (int i = 0; i < producePosition.length; i++) {
            if (producePosition[i] == null) {
                return false;
            }
        }
        return true;
    }

    /**
     * 在容器填一次数据
     * 当容器已满,就等待
     * 等到被通知再继续填充
     * 填充一次以后,通知未空
     */
    public void set() {
        try {
            cook.acquire();
            lock.lock();
            while (isFull()) {
                setCondition.await();
            }
            for (int i = 0; i < producePosition.length; i++) {
                if (producePosition[i] == null) {
                    producePosition[i] = "food";
                    System.out.println(Thread.currentThread().getName() + " cook " + producePosition[i] + i);
                    break;
                }
            }
            getCondition.signalAll();
            lock.unlock();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            cook.release();
        }
    }

    /**
     * 在容器取一次数据
     * 当容器已空时,就等待
     * 等到被通知再继续取
     * 取一次以后,通知未满
     */
    public void get() {
        try {
            diner.acquire();
            lock.lock();
            while (isEmpty()) {
                getCondition.await();
            }
            for (int i = 0; i < producePosition.length; i++) {
                if (producePosition[i] != null) {
                    System.out.println(Thread.currentThread().getName() + " eat food" + i);
                    producePosition[i] = null;
                    break;
                }
            }
            setCondition.signalAll();
            lock.unlock();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            diner.release();
        }
    }
}


测试类


package com.lhc.concurrent.semaphore.repast;

public class CookThread extends Thread {
    private RepastService repastService;

    public CookThread(RepastService repastService) {
        this.repastService = repastService;
    }

    @Override
    public void run() {
        repastService.set();
    }

    public static void main(String[] args) throws InterruptedException{
        RepastService repastService = new RepastService();
        CookThread[] cookThreads = new CookThread[20];
        EatThread[] eatThreads = new EatThread[20];

        for (int i = 0; i < 20; i++){
            cookThreads[i] = new CookThread(repastService);
            eatThreads[i] = new EatThread(repastService);
        }
        Thread.sleep(2000);
        for (int i = 0; i < 20; i++){
            cookThreads[i].start();
            eatThreads[i].start();
        }
    }
}


package com.lhc.concurrent.semaphore.repast;

public class EatThread extends Thread {
    private RepastService repastService;

    public EatThread(RepastService repastService) {
        this.repastService = repastService;
    }

    @Override
    public void run() {
        repastService.get();
    }
}


测试结果

Thread-0 cook food0
Thread-11 eat food0
Thread-8 cook food0
Thread-4 cook food1
Thread-2 cook food2
Thread-3 eat food0
Thread-16 cook food0
Thread-18 cook food3
Thread-5 eat food0
Thread-26 cook food0
Thread-1 eat food0
Thread-28 cook food0
Thread-15 eat food0
Thread-6 cook food0
Thread-9 eat food0
Thread-19 eat food1
Thread-7 eat food2
Thread-38 cook food0
Thread-12 cook food1
Thread-14 cook food2
Thread-13 eat food0
Thread-29 eat food1
Thread-30 cook food0
Thread-24 cook food1
Thread-17 eat food0
Thread-25 eat food1
Thread-36 cook food0
Thread-21 eat food0
Thread-23 eat food2
Thread-37 eat food3
Thread-20 cook food0
Thread-32 cook food1
Thread-22 cook food2
Thread-34 cook food3
Thread-31 eat food0
Thread-27 eat food1
Thread-10 cook food0
Thread-33 eat food0
Thread-35 eat food2
Thread-39 eat food3

猜你喜欢

转载自blog.csdn.net/TP89757/article/details/89420058