在Java多线程编程中,生产者消费者模式是一种常见的设计模式,用于协调生产者线程和消费者线程之间的协作,确保资源的有效利用和同步。在这个示例中,使用了Java的`java.util.concurrent.locks`包中的`Lock`接口和`Condition`接口来实现这一模式。`Lock`接口提供了比`synchronized`更精细的锁控制,而`Condition`接口则允许我们创建特定条件的等待队列。
我们来看一下`ProducerConsumerDemo`类的核心结构。这个类中有一个`bufferList`列表作为共享资源,即生产者生产的商品和消费者消费的商品都会存储在这里。`bufferSize`变量表示缓冲区的容量。`ReentrantLock`是`Lock`的一个实现,它提供了可重入的锁定机制,确保线程安全。`condition`是`ReentrantLock`的`Condition`实例,用于控制线程的等待与唤醒。
`produce()`方法是生产者的逻辑,首先获取锁,然后检查缓冲区是否已满。如果满,生产者线程会调用`condition.await()`进入等待状态,释放锁。这样,其他生产者线程也无法继续生产,避免了缓冲区溢出的问题。当缓冲区未满时,生产者添加一个商品到缓冲区,并通过`condition.signalAll()`唤醒所有等待的消费者线程,告知他们有新的商品可以消费。
`consume()`方法是消费者的逻辑,与生产者类似,先获取锁,然后检查缓冲区是否为空。如果空,消费者线程会调用`await()`进入等待状态,释放锁,直到被其他线程唤醒。当缓冲区非空时,消费者可以从缓冲区取出一个商品并消费,然后同样通过`signalAll()`唤醒所有等待的生产者线程,告知他们缓冲区有了空间可以生产。
这个示例展示了如何使用`Lock`和`Condition`来实现生产者消费者模式的基本逻辑。`Lock`接口相比`synchronized`关键字的优势在于它可以更灵活地控制锁的获取和释放,以及条件的等待和唤醒。此外,`Condition`接口可以创建多个条件,使得线程等待更加精细化,可以根据不同条件进行等待和唤醒,提高了程序的并发性能和灵活性。
在实际应用中,我们可能还需要考虑异常处理,例如在获取或释放锁时可能会抛出`InterruptedException`,需要适当地捕获和处理。此外,还可以使用`tryLock()`方法尝试获取锁,以避免长时间等待导致的阻塞。对于更复杂的场景,可以考虑使用`BlockingQueue`,如`ArrayBlockingQueue`,它内置了对生产者消费者模式的支持,简化了同步操作。