• Tags
  •         
  • www.breakyizhan.com
  •    

    在计算中,生产者 - 消费者问题(也称为有界缓冲问题)是多进程同步问题的典型示例。该问题描述了两个进程,即生产者和使用者,它们共享一个用作队列的通用固定大小缓冲区。

    • 生产者的工作是生成数据,将其放入缓冲区,然后重新开始。
    • 同时,消费者正在消费数据(即从缓冲区中删除数据),一次一件。

    问题
    确保生成器不会尝试将数据添加到缓冲区(如果已满)并且使用者不会尝试从空缓冲区中删除数据。

    解决方案
    如果缓冲区已满,生产者要么进入睡眠状态要么丢弃数据。消费者下次从缓冲区中删除项目时,它会通知生产者,生产者再次开始填充缓冲区。以同样的方式,如果消费者发现缓冲区为空,则消费者可以进入睡眠状态。下一次生产者将数据放入缓冲区时,它会唤醒睡眠消费者。
    解决方案不充分可能导致两个进程等待唤醒的死锁。

    推荐阅读- 在多线程JAVAJAVA中同步线程间通信

    JAVA中,线程的生产者消费者类的实施

    • 一个LinkedList的名单 -存储在队列中的作业清单。
    • 可变容量 - 检查列表是否已满
    • 一种控制从此列表中插入和提取的机制,以便我们不会在列表中填充,如果它是空的,则不会插入到列表中,如果它是空的,则不从中删除。

     

     

    // Java program to implement solution of producer
    // consumer problem.
    import java.util.LinkedList;
    public class Threadexample
    {
        public static void main(String[] args)
                            throws InterruptedException
        {
            // Object of a class that has both produce()
            // and consume() methods
            final PC pc = new PC();
            // Create producer thread
            Thread t1 = new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    try
                    {
                        pc.produce();
                    }
                    catch(InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            });
            // Create consumer thread
            Thread t2 = new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    try
                    {
                        pc.consume();
                    }
                    catch(InterruptedException e)
                    {
                        e.printStackTrace();
                    }
                }
            });
            // Start both threads
            t1.start();
            t2.start();
            // t1 finishes before t2
            t1.join();
            t2.join();
        }
        // This class has a list, producer (adds items to list
        // and consumber (removes items).
        public static class PC
        {
            // Create a list shared by producer and consumer
            // Size of list is 2.
            LinkedList<Integer> list = new LinkedList<>();
            int capacity = 2;
            // Function called by producer thread
            public void produce() throws InterruptedException
            {
                int value = 0;
                while (true)
                {
                    synchronized (this)
                    {
                        // producer thread waits while list
                        // is full
                        while (list.size()==capacity)
                            wait();
                        System.out.println("Producer produced-"
                                                      + value);
                        // to insert the jobs in the list
                        list.add(value++);
                        // notifies the consumer thread that
                        // now it can start consuming
                        notify();
                        // makes the working of program easier
                        // to  understand
                        Thread.sleep(1000);
                    }
                }
            }
            // Function called by consumer thread
            public void consume() throws InterruptedException
            {
                while (true)
                {
                    synchronized (this)
                    {
                        // consumer thread waits while list
                        // is empty
                        while (list.size()==0)
                            wait();
                        //to retrive the ifrst job in the list
                        int val = list.removeFirst();
                        System.out.println("Consumer consumed-"
                                                        + val);
                        // Wake up producer thread
                        notify();
                        // and sleep
                        Thread.sleep(1000);
                    }
                }
            }
        }
    }
    

    输出:

    Producer produced-0
    Producer produced-1
    Consumer consumed-0
    Consumer consumed-1
    Producer produced-2

    重点

    • PC类(具有生成和使用方法的类)中,添加了一个作业链接列表和列表容量,以检查生成器是否在列表已满时不生成。
    • Producer类中,该值初始化为0。
      • 此外,我们有一个无限的外部循环来插入列表中的值。在这个循环中,我们有一个synchronized块,所以一次只运行一个生产者或一个消费者线程。
      • 在将作业添加到列表之前存在内部循环,该列表检查作业列表是否已满,生产者线程放弃PC上的内部锁定并继续等待状态。
      • 如果列表为空,则控件传递到循环下方,并在列表中添加一个值。
    • Consumer类中,我们再次有一个无限循环来从列表中提取值。
      • 在里面,我们还有一个内部循环,用于检查列表是否为空。
      • 如果它是空的,那么我们让消费者线程放弃PC上的锁并将控制传递给生产者线程以产生更多的工作。
      • 如果列表不为空,我们绕过循环并从列表中删除一个项目。
    • 在这两种方法中,我们在所有语句的末尾使用notify。原因很简单,一旦你在列表中有东西,你可以让消费者线程消费它,或者如果你已经消费了东西,你可以让生产者产生一些东西。
    • 两个方法结束时的sleep()只是使程序的输出以步进方式运行,而不是一次显示所有内容,以便您可以看到程序中实际发生的情况。

     
    转载请保留页面地址:https://www.breakyizhan.com/java/4964.html