龙空技术网

怎样使用Java模拟实现一个生产者与消费者

GeekFever 136

前言:

如今我们对“生产者消费者c语言”大致比较关怀,兄弟们都想要剖析一些“生产者消费者c语言”的相关资讯。那么小编在网络上收集了一些关于“生产者消费者c语言””的相关文章,希望兄弟们能喜欢,你们快快来了解一下吧!

本文中,介绍了使用 Java 实现生产者和消费者之间的协作的方法。首先我们介绍了使用 wait() 和 notify() 方法的方法,并给出了一个示例代码。然后解释了这种方法的原理,并指出了它的局限性。最后,介绍了 Java 5 之后提供的一些新的类,可以用来实现生产者和消费者之间的协作,这些类可以在多核 CPU 的环境下获得更好的性能。

下面是一个示例代码,使用了 Java 的 wait() 和 notify() 方法来实现生产者和消费者之间的协调:

import java.util.LinkedList;public class ProducerConsumer {    private LinkedList<Integer> list = new LinkedList<>();    private final int LIMIT = 10;    private final Object lock = new Object();    public void produce() throws InterruptedException {        int value = 0;        while (true) {            synchronized (lock) {                while (list.size() == LIMIT) {                    lock.wait();                }                list.add(value++);                lock.notify();            }        }    }    public void consume() throws InterruptedException {        while (true) {            synchronized (lock) {                while (list.size() == 0) {                    lock.wait();                }                System.out.print("集合大小是: " + list.size());                int value = list.removeFirst();                System.out.println("; 值等于: " + value);                lock.notify();            }            Thread.sleep(100);        }    }}

在这个生产者和消费者的例子中,我们使用了 Java 的 wait() 和 notify() 方法来实现生产者和消费者之间的协调。这两个方法是 Object 类中的 native 方法,用于让当前线程等待或唤醒其他线程。

wait() 方法会使当前线程等待,并且释放当前锁,直到其他线程调用 notify() 方法或 notifyAll() 方法唤醒它为止。notify() 方法会唤醒等待在当前锁上的一个线程,而 notifyAll() 方法则会唤醒所有等待在当前锁上的线程。

我们使用了一个 LinkedList 作为缓冲区,并使用一个锁来保护这个缓冲区。生产者方法中,我们使用 while (list.size() == LIMIT) lock.wait() 来检查缓冲区是否已满,如果已满就调用 wait() 方法等待;消费者方法中,我们使用 while (list.size() == 0) lock.wait() 来检查缓冲区是否已空,如果已空就调用 wait() 方法等待。

这样,当缓冲区满的时候,生产者就会被阻塞,等待消费者取走一些元素;当缓冲区空的时候,消费者就会被阻塞,等待生产者生产一些元素。这样,生产者和消费者就可以协调起来,避免生产者把缓冲区填满或者消费者把缓冲区取空,在生产者向缓冲区添加一个元素或者消费者从缓冲区取出一个元素后,就调用 lock.notify() 方法来唤醒等待的线程。这样,生产者就可以继续往缓冲区里添加元素,消费者就可以继续从缓冲区里取出元素,我们使用的是 while (list.size() == LIMIT) lock.wait() 和 while (list.size() == 0) lock.wait() 来检查缓冲区是否已满或已空,这样可以避免虚假唤醒的问题。如果改成 if (list.size() == LIMIT) lock.wait() 或者 if (list.size() == 0) lock.wait(),那么就有可能出现虚假唤醒的情况,因为这个条件可能在 wait() 方法返回之前就已经不成立了,生产者和消费者是在不断地运行的,但是你也可以使用其他方式来控制生产者和消费者的运行。例如,你可以使用一个标志位来指示生产者和消费者的运行状态,在生产者或消费者完成任务之后设置这个标志位,然后等待其他线程改变这个标志位后再继续执行。这样,就可以在控制生产者和消费者的运行状态的同时,也可以使用 wait() 和 notify() 方法来协调生产者和消费者之间的协作,我们使用的是一个 LinkedList 做为缓冲区,并使用一个锁来保护这个缓冲区。你也可以使用其他的数据结构作为缓冲区,例如 ArrayBlockingQueue、LinkedBlockingQueue 等,这些数据结构都是线程安全的,可以直接用来实现生产者和消费者之间的协作。

下面是测试代码:

public class Test {    public static void main(String[] args) throws InterruptedException {        ProducerConsumer pc = new ProducerConsumer();        Thread t1 = new Thread(new Runnable() {            @Override            public void run() {                try {                    pc.produce();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        });        Thread t2 = new Thread(new Runnable() {            @Override            public void run() {                try {                    pc.consume();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        });        t1.start();        t2.start();        t1.join();        t2.join();    }}

下面是打印的结果集:

生产者和消费者之间的协作

Java 的 wait() 和 notify() 方法可以用来实现生产者和消费者之间的协作,你可以使用这两个方法来控制线程的运行,避免生产者把缓冲区填满或者消费者把缓冲区取空。你也可以使用其他的数据结构作为缓冲区,并使用其他的方式来控制生产者和消费者的运行。

总的来说,使用 wait() 和 notify() 方法来实现生产者和消费者之间的协作是一种常用的方法。但是,这种方法有一个很大的局限性,就是必须使用 synchronized 关键字来保护共享资源。这意味着,只有一个线程能够访问共享资源,其他线程必须等待。这在多核 CPU 的环境下可能会带来性能的损失。

Java 5 之后提供了一些新的类,可以用来实现生产者和消费者之间的协作,例如 BlockingQueue、CountDownLatch 和 CyclicBarrier。这些类都是在 java.util.concurrent 包中定义的,使用这些类可以实现同步,但是不需要使用 synchronized 关键字,因此可以在多核 CPU 的环境下获得更好的性能。

创作不易,喜欢的朋友点赞收藏关注,谢谢!

标签: #生产者消费者c语言