如何使用信号量解决消费者/生产者的任务 [英] How solve consumer/producer task using semaphores

查看:197
本文介绍了如何使用信号量解决消费者/生产者的任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个SimpleProducerConsumer类,该类说明了消费者/生产者的问题(我不确定这是正确的).

I have a SimpleProducerConsumer class that illustrates a consumer/producer problem (I am not sure that it's correct).

public class SimpleProducerConsumer {
    private Stack<Object> stack = new Stack<Object>();
    private static final int STACK_MAX_SIZE = 10;

    public static void main(String[] args) {
        SimpleProducerConsumer pc = new SimpleProducerConsumer();
        new Thread(pc.new Producer(), "p1").start();
        new Thread(pc.new Producer(), "p2").start();
        new Thread(pc.new Consumer(), "c1").start();
        new Thread(pc.new Consumer(), "c2").start();
        new Thread(pc.new Consumer(), "c3").start();
    }

    public synchronized void push(Object d) {
        while (stack.size() >= STACK_MAX_SIZE)
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        stack.push(new Object());
        System.out.println("push " + Thread.currentThread().getName() + "    " + stack.size());
        notify();
    }

    public synchronized Object pop() {
        while (stack.size() == 0)
            try {
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        stack.pop();
        System.out.println("pop  " + Thread.currentThread().getName() + "    " + stack.size());
        notify();
        return null;
    }

    class Consumer implements Runnable {
        @Override
        public void run() {
            while (true) {
                pop();
            }
        }
    }

    class Producer implements Runnable {
        @Override
        public void run() {
            while (true) {
                push(new Object());
            }
        }
    }
}

我在此处找到了信号灯的简单实现. (我知道有并发包) 我该如何更改代码以将Java对象的监视器交换为我的自定义信号量? (以说明使用信号量的C/P问题)

I found simple realization of semaphore here. (I know that there is concurrency package) How do I need to change code to exchange the java object's monitors to my custom semaphore? (To illustrate C/P problem using semaphores)

信号量:

class Semaphore {
    private int counter;

    public Semaphore() {
        this(0);
    }

    public Semaphore(int i) {
        if (i < 0)
            throw new IllegalArgumentException(i + " < 0");
        counter = i;
    }

    public synchronized void release() {
        if (counter == 0) {
            notify();
        }
        counter++;
    }

    public synchronized void acquire() throws InterruptedException {
        while (counter == 0) {
            wait();
        }
        counter--;
    }
}

推荐答案

首先,您应该修复测试应用. sleep()调用是什么?我可以在生产者",消费者"测试线程中理解它们,但是为什么它们在push/pop方法中呢?此外,测试线程会传输某些对象,但是无法检查每个推送的对象是否完全弹出一次.

First, you should fix your test app. What's with the sleep() calls? I could understand them, maybe, in the 'Producer', 'Consumer' test threads, but why are they in the push/pop methods? Also, the test threads transfer some object, but there is no check that each pushed object is popped exactly once.

基于信号量的生产者-消费者队列相当琐碎.仅基于信号量的有界队列需要三个,一个初始化为零以对队列中的对象进行计数,另一个初始化为队列大小以对空插槽进行计数,另一个初始化为1以充当互斥体并保护队列免受多次访问.只是Google的生产者消费者".

A semaphore-based producer-consumer queue is fairly trivial. A bounded queue based solely on semaphores needs three, one initialized to zero to count objects in the queue, another initialized to the queue size to count empty slots and one initialized to 1 to act as a mutex and protect the queue from multiple access. Just Google 'producer consumer'.

可以使用两个队列和一个具有int计数的消息类来完成测试.创建大量具有顺序计数的对象,并将它们推入一个队列,然后启动线程重载,使两个队列周围的对象随机播放.当您停止线程时(确定,还需要终止bool),这两个队列应包含所有原始对象-没有多余的对象,没有短缺的对象和没有重复的对象.

Testing can be done with two queues and a message class that has an int count. Create a lot of objects with a sequential count and push them onto one queue, then start a load of threads that shuffle objects around the two queues. When you stop the threads, (OK, you need a terminate bool as well), the two queues should contain all the original objects - no extras, no shortages and no duplicates.

这篇关于如何使用信号量解决消费者/生产者的任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆