0

我正在尝试在 java 中实现生产者消费者问题。我正在使用循环缓冲区(循环数组)让生产者将项目插入缓冲区。以下是我的代码:

import java.util.*;
import java.io.*;

public class Buffer
{
    String a[];
    int front, rear;

    public Buffer(int size)
    {
            a = new String[size];
            front = rear = -1;
    }

    public boolean insert(String dataitem)
    {
            int p;
            p = (rear+1) % a.length;

            if(p==front)
            {
                    System.out.println("Buffer full");
                    return false;
            }
            else
            {       rear = p;
                    a[rear] = dataitem;
                    if(front == -1)
                            front = 0;
                    return true;
            }
    }

    public boolean empty()
    {
            if(front == -1)
                    return true;
            else
                    return false;
    }

    public String delete()
    {
            String result = a[front];
            if(front == rear)
                    front = rear = -1;
            else
                    front = (front +1)%a.length;
            return result;
    }

    public void display()
    {
            if(front == -1)
                    System.out.println("Buffer empty");
else
            {
                    System.out.println("Buffer elements are:");
                    int i= front;

                    while(i!= rear)
                    {
                            System.out.println(a[i]);
                            i = (i+1)%a.length;
                    }
                    System.out.println(a[i]);
            }
    }


    public static void main(String[] args)
    {
            int size = Integer.parseInt(args[0]);

            Buffer b = new Buffer(size);
            int ch;
            String dataitem, msg;

            Thread prod = new Thread(new Producer(b, size));
            Thread cons = new Thread(new Consumer(b, size));

            prod.start();
            cons.start();
    }

}

class Producer extends Thread
{
    Buffer b;
    int size;

    public Producer(Buffer b, int size)
    {
            this.b = b;
            this.size = size;
    }

    public void run()
    {
            while(true)
            {
                    synchronized(b)
                    {
                    for(int i = 1; i <= size; i++)
                    {
                            try
                            {       String dataitem = Thread.currentThread().getId()+"_"+i;
                                    boolean bool = b.insert(dataitem);
                                    //b.notifyAll();
if(bool)
                                            System.out.println("Successfully inserted "+dataitem);
                                    b.notifyAll();
                                    Thread.sleep(2000);
                            }
                            catch(Exception e)
                            {       e.printStackTrace();
                            }
                    }

            }
            }
    }
}

class Consumer extends Thread
{
    Buffer b;
    int size;

    public Consumer(Buffer b, int size)
    {
            this.b = b;
            this.size = size;
    }

    public void run()
    {
            while(b.empty())
            {
                    synchronized(b)
                    {
                            try
                            {
                                    System.out.println("Buffer empty");
                                    b.wait();
                            }
                            catch(Exception e)
                            {       e.printStackTrace();
                            }
                    }
            }

            synchronized(b)
            {
                    b.notifyAll();
                    String dataitem = b.delete();
                    System.out.println("Removed "+dataitem);
            }

    }
}

生产者正在成功地将数据项插入缓冲区。但它们并没有被消费者消费。

当我执行程序时,我得到以下输出。

Successfully inserted 11_1
Successfully inserted 11_2
Buffer full
Buffer full
Buffer full
Buffer full
Buffer full
Buffer full

我的问题是如何让消费者从缓冲区消费项目?

4

1 回答 1

1

主要问题是synchronized您的块Producer太宽了。它永远不会让Consumer获取锁

从缩小范围开始,例如...

while (true) {
    for (int i = 1; i <= size; i++) {
        try {
            String dataitem = Thread.currentThread().getId() + "_" + i;
            boolean bool = b.insert(dataitem);
            //b.notifyAll();
            if (bool) {
                System.out.println("Successfully inserted " + dataitem);
            }
            synchronized (b) {
                b.notifyAll();
            }
            Thread.sleep(2000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

您也可以考虑同步 inginsertdelete方法本身。我个人很想使用内部锁,但你可以简单地synchronize使用方法本身,例如......

public synchronized boolean insert(String dataitem) {...}

public synchronized String delete() {...}

就目前而言,你Consumer只会从缓冲区中读取一个值,但我会让你弄清楚那个;)

附带说明一下,我可能会将等待和通知功能直接放在 中Buffer,这样无论何时您尝试delete输入一个值,它都会在delete方法中等待Buffer不为空,并允许该insert方法自己发出通知。 .但那是我;)

同样,我可能会考虑阻止该insert方法,直到有更多空间,但这将归结为您希望如何实现它:P

更新

基本上,这将开始给出您正在寻找的结果......

public class ProducerConsumer {

    public static void main(String[] args) {
        new ProducerConsumer();
    }

    public ProducerConsumer() {
        int size = 5;

        Buffer b = new Buffer(size);

        Thread prod = new Thread(new Producer(b, size));
        Thread cons = new Thread(new Consumer(b, size));

        prod.start();
        cons.start();
    }

    public class Buffer {

        String a[];
        int front, rear;

        public Buffer(int size) {
            a = new String[size];
            front = rear = -1;
        }

        public synchronized boolean insert(String dataitem) {
            int p;
            p = (rear + 1) % a.length;

            if (p == front) {
                System.out.println("Buffer full");
                return false;
            } else {
                rear = p;
                a[rear] = dataitem;
                if (front == -1) {
                    front = 0;
                }
                return true;
            }
        }

        public boolean empty() {
            return front == -1;
        }

        public synchronized String delete() {
            String result = a[front];
            if (front == rear) {
                front = rear = -1;
            } else {
                front = (front + 1) % a.length;
            }
            return result;
        }

        public void display() {
            if (front == -1) {
                System.out.println("Buffer empty");
            } else {
                System.out.println("Buffer elements are:");
                int i = front;

                while (i != rear) {
                    System.out.println(a[i]);
                    i = (i + 1) % a.length;
                }
                System.out.println(a[i]);
            }
        }

    }

    class Producer extends Thread {

        Buffer b;
        int size;

        public Producer(Buffer b, int size) {
            this.b = b;
            this.size = size;
        }

        public void run() {
            int i = 0;
            while (true) {
                try {
                    String dataitem = Thread.currentThread().getId() + "_" + ++i;
                    boolean bool = b.insert(dataitem);
                    if (bool) {
                        System.out.println("Successfully inserted " + dataitem);
                    }
                    synchronized (b) {
                        b.notifyAll();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }
        }
    }

    class Consumer extends Thread {

        Buffer b;
        int size;

        public Consumer(Buffer b, int size) {
            this.b = b;
            this.size = size;
        }

        public void run() {

            while (true) {

                while (b.empty()) {
                    synchronized (b) {
                        try {
                            System.out.println("Buffer empty");
                            b.wait();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }

                String dataitem = null;
                synchronized (b) {
                    dataitem = b.delete();
                }
                    System.out.println("Removed " + dataitem);
            }
        }
    }
}
于 2013-11-06T02:04:13.503 回答