java - java多线程中的生产者消费者

标签 java multithreading consumer producer

我正在尝试用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

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

最佳答案

主要问题是 Producer 中的 synchronized block 太宽。它永远不会让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();
        }
    }
}

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

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

public synchronized String delete() {...}

就目前情况而言,您的 Consumer 只会从缓冲区读取单个值,但我会让您弄清楚这个值;)

作为旁注,我可能会将等待和通知功能直接放在 Buffer 中,这样每当您尝试删除一个值时,它就会在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);
            }
        }
    }
}

关于java - java多线程中的生产者消费者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19802639/

相关文章:

linux - 每个信号量的线程堆栈是多少

java - 根据选择的选项动态添加图像

java - Spring Data Jpa OneToMany 同时保存子实体和父实体?

java - put() 之后哈希表仍为空

java - 如何更改消费者之外的列表

java - Jython 函数到 java 消费者

c - 如何使用execl()执行另一个程序

java - 2way ssl 与 java

扩展抽象类的Java过程

c++ - 使用多线程编程的调度器