Producer-Consumer使用Java中的堆栈

时间:2013-05-09 06:53:14

标签: java multithreading concurrency producer-consumer

我使用堆栈作为我的存储来实现我的Producer-Consumer模型。

public class Main {

/**
 * @param args
 */
public static void main(String[] args) {
    Stackable<Integer> stack = new MyArrayStack<Integer>();
    Producer producer = new Producer(stack);
    Consumer consumer = new Consumer(stack);
    producer.start();
    consumer.start();
}

private static class Producer extends Thread {
    public Producer(Stackable<Integer> s) {
        mStack = s;
    }

    private Stackable<Integer> mStack = null;
    private int mNumber = 0;

    @Override
    public void run() {
        // TODO generates number here
        while(true){        synchronized(this){
                while(!mStack.isEmpty())
                {
                    try{
                        this.wait();
                    } catch(Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            mNumber++;
            System.out.println("Producer generates number:" + mNumber);
            mStack.push(mNumber);
            this.notifyAll();
            }
        }   
    }
}

private static class Consumer extends Thread {
    public Consumer(Stackable<Integer> s) {
        mStack = s;
    }

    private Stackable<Integer> mStack = null;

    @Override
    public void run() {
        // TODO consume number here.
        while(true){
            synchronized(this){
                while(mStack.isEmpty())
                {
                    try{
                        this.wait();
                    } catch(Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            int number = mStack.pop();
            System.out.println("Consumer consumes number:" + number);
            this.notifyAll();
            }
        }}

}

}

然而,当我测试程序时,似乎只有生产者才会工作,它会不断生成数字而消费者线程似乎无法正常工作。

专家可以帮我调试我的代码出错吗?感谢。

编辑:我的堆栈代码是:     公共类MyArrayStack实现Stackable {

private static final int DEFAULT_SIZE = 16;
protected int sp; // empty stack
protected E[] head; // array
private int size;
private int count;

MyArrayStack(int size) {
    if (size <= 0)
          throw new IllegalArgumentException(
                     "Stack's capacity must be positive");
    head = (E[])new Object[size];
    sp = -1;
    count=0;

}






public boolean isFull() {
    return sp == this.size -1;
}

@Override
public void push(Object e) {

    if (!isFull())
    {
        head[++sp] = (E) e;
        count++;
    }

}

@Override
public E pick() {
    if (sp == -1)
        try {
            throw new Exception("Stack is empty");
        } catch (Exception e) {

            e.printStackTrace();
        }
    return head[sp];
}

@Override
public E pop() {
    count--;
    if (isEmpty()) {
        return null;
    } else
        return head[sp--];

}

@Override
public int count() {

    return count;
}

@Override
public boolean isEmpty() {

    return (sp == -1);
}
}

2 个答案:

答案 0 :(得分:1)

哦,哦。我有问题,你在同步这个,而不是在堆栈对象上同步,如synchronized(mStack){

然后等待并通知此对象。

添加代码为您提供帮助。我在我的代码中更改了堆栈列表,因为我没有你的堆栈对象。

private static class Producer extends Thread {
    public Producer(List<Integer> s) {
        mStack = s;
    }

    private List<Integer> mStack = null;
    private int mNumber = 0;

    @Override
    public void run() {
        // TODO generates number here
        while(true){        synchronized(mStack){
                while(!mStack.isEmpty())
                {
                    try{
                        mStack.wait();
                    } catch(Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            mNumber++;
            System.out.println("Producer generates number:" + mNumber);
            mStack.add(mNumber);
            mStack.notify();
            }
        }   
    }
}

private static class Consumer extends Thread {
    public Consumer(List<Integer> s) {
        mStack = s;
    }

    private List<Integer> mStack = null;

    @Override
    public void run() {
        // TODO consume number here.
        while(true){
            synchronized(mStack){
                while(mStack.isEmpty())
                {
                    try{
                         mStack.wait();
                    } catch(Exception e)
                    {
                        e.printStackTrace();
                    }
                }
            int number = mStack.remove(0);
            System.out.println("Consumer consumes number:" + number);
            mStack.notify();
            }
        }}

}}

答案 1 :(得分:1)

要解决您的问题,您应该synchronize并在wait()而不是notifyAll()致电mStackthis。通过在this中使用Producer等待生产者对象,并在Consumer中等待消费者对象,这是不正确的。因此,您必须在同一个对象wait()上调用notifyAll()mStack

以下是可以正常使用的代码段:

package com.thread.concurrency;

import java.util.LinkedList;
import java.util.List;

public class Main {

    public static void main(String[] args) {
        Main mainObj = new Main();
        List<Integer> stack = new LinkedList<Integer>();
        Producer producer = mainObj.new Producer(stack);
        Consumer consumer = mainObj.new Consumer(stack);
        producer.start();
        consumer.start();
    }

    private class Producer extends Thread {
        public Producer(List<Integer> s) {
            mStack = s;
        }

        private List<Integer> mStack = null;
        private int mNumber = 0;

        @Override
        public void run() {
            // TODO generates number here
            while (true) {
                synchronized (mStack) {
                    while(!mStack.isEmpty())
                    {
                        try{
                            mStack.wait(); // this.wait();
                        } catch(Exception e)
                        {
                            e.printStackTrace();
                        }
                    }
                mNumber++;
                System.out.println("Producer generates number:" + mNumber);
                mStack.add(mNumber);
                    mStack.notifyAll();// this.notifyAll();
                }
            }   
        }
    }

    private class Consumer extends Thread {
        public Consumer(List<Integer> s) {
            mStack = s;
        }

        private List<Integer> mStack = null;

        @Override
        public void run() {
            // TODO consume number here.
            while(true){
                synchronized (mStack) {
                    while(mStack.isEmpty())
                    {
                        try{
                            mStack.wait(); // this.wait();
                        } catch(Exception e)
                        {
                            e.printStackTrace();
                        }
                    }
                int number = ((LinkedList<Integer>) mStack).removeLast();
                System.out.println("Consumer consumes number:" + number);
                    mStack.notifyAll();// this.notifyAll();
                }
            }}

    }
}