Java---producer and consumer mode

The so-called producer-consumer problem actually mainly includes two types of threads. One is that the producer thread is used to produce data, and the other is that the consumer thread is used to consume data. In order to decouple the relationship between producers and consumers, a shared data area is usually used, just like a warehouse. The producer directly places the data in the shared data area after producing the data, and does not need to care about the behavior of the consumer. Consumers only need to obtain data from the shared data area, and no longer need to care about the behavior of producers. However, this shared data area should have such a concurrent collaboration function between threads:

  • If the shared data area is full, the blocked producer continues to produce data and put it in;
  • If the shared data area is empty, the blocked consumer continues to consume data.

In the Java language, there are three ways to implement the producer-consumer problem:

  • Use the message notification mechanism of Object's wait/notify;
  • Use Lock's Condition's await/signal message notification mechanism;
  • Implemented using BlockingQueue.

1. Object's wait/notify message notification mechanism

Reference:
waitnotify of inter-thread communication Object:
https://blog.csdn.net/m0_37450089/article/details/120222872

insert image description here

The waiting/notification mechanism mainly provides three methods for communication between threads

  • wait() The current thread releases the lock and enters the waiting (blocking) state
  • notify() wakes up a thread that is waiting for the corresponding object lock to enter the ready queue so that it can continue to compete for the lock after the current thread releases the lock
  • notifyAll() wakes up all threads that are waiting for the corresponding object lock to enter the ready queue so that the current thread can continue to compete for the lock after releasing the lock

The waiting/notification mechanism means that one thread A calls the wait() method of the object Object to enter the waiting state, and another thread B calls the notify() or notifyAll() method of the object Object. When thread A receives the notification, it can Return from the wait() method of the object Object, and then perform subsequent operations. The communication between threads needs to be completed by the object Object. The wait(), notify(), and notifyAll() methods in the object are like switch signals, which are used to complete the interaction between the waiting party and the notifying party.

2. Lock's Condition's await/signal message notification mechanism

Quote: Detailed explanation of Condition's await and signal waiting/notification mechanism
https://blog.csdn.net/belalds/article/details/109612454

Any java object inherits from the Object class, and communication between threads is often applied to several methods of Object, such as wait(), wait(long timeout), wait(long timeout, int nanos) and notify(), notifyAll () Several methods implement the waiting/notification mechanism.
Similarly, there will still be the same method to implement the waiting/notification mechanism under the java Lock system.
On the whole, wait and notify/notify of Object cooperate with the object monitor to complete the waiting/notification mechanism between threads, while Condition and Lock cooperate to complete the waiting notification mechanism. The former is at the bottom level of java, and the latter is at the language level. It has higher controllability and scalability. In addition to the difference in the way of use, the two still have many differences in functional characteristics:

  • Condition can support not responding to interrupts, but it does not support it by using Object;
  • Condition can support multiple waiting queues (new multiple Condition objects), while the Object method can only support one;
  • Condition can support the setting of timeout, but Object does not support it

The wait method for Object

  • void await() throws InterruptedException: The current thread enters the waiting state. If other threads call the signal or signalAll method of the condition and the current thread obtains the Lock and returns from the await method, if it is interrupted in the waiting state, an interrupted exception will be thrown;
  • long awaitNanos(long nanosTimeout): The current thread enters the waiting state until it is notified, interrupted or timed out;
  • boolean await(long time, TimeUnit unit) throws InterruptedException: Same as the second one, supports custom time unit
  • boolean awaitUntil(Date deadline)
    throws InterruptedException: The current thread enters the waiting state until it is notified, interrupted or a certain time

notify/notifyAll method for Object

  • void signal(): wake up a thread waiting on the condition, transfer the thread from the waiting queue to the synchronization queue, and return from the waiting method if the lock can be competed in the synchronization queue.
  • void signalAll(): The difference from 1 is that it can wake up all threads waiting on the condition

3. Implemented using BlockingQueue

Reference: BlockingQueue (blocking queue)
https://blog.csdn.net/Student111w/article/details/118887900

A blocking queue (BlockingQueue) is a queue that supports two additional operations. These two additional operations are: when the queue is empty, the thread getting the element waits for the queue to become non-empty. When the queue is full, the thread storing the element waits for the queue to become available. Blocking queues are often used in the scenario of producers and consumers. The producer is the thread that adds elements to the queue, and the consumer is the thread that takes elements from the queue. A blocking queue is a container where producers store elements, and consumers only take elements from the container.

Guess you like

Origin blog.csdn.net/chenfang0529/article/details/126064334