Multithreading-blocking queue (producer-consumer model)

Blocking queue

Producer consumer model

  • The producer-consumer model is to solve the problem of strong coupling between producers and consumers through a container. The producer and the consumer do not communicate directly with each other, but communicate through the blocking queue , so the producer does not need to wait for the consumer to process the data after producing the data, and throws it directly to the blocking queue. The consumer does not ask the producer for the data, but Directly taken from the blocking queue, the blocking queue is equivalent to a buffer, which balances the processing capabilities of the producer and the consumer . This blocking queue is used to decouple producers and consumers .

I believe you have learned that the model needs to use two methods wait() and notify(); (one is waiting, the other is waking up)

1. Need to use Object.wait () method (wait)

  • The wait() method is to stop the thread from running .
  1. The function of the wait() method is to make the thread currently executing the code wait. The wait() method is a method of the Object class. This method is used to put the current thread into the "pre-execution queue" where wait() is located. The code stops executing until notified or interrupted.
  2. The wait() method can only be called in a synchronized method or synchronized block . If the appropriate lock is not held when wait() is called , an exception will be thrown .
  3. After the wait() method is executed, the current thread releases the lock , and the thread competes with other threads to reacquire the lock.
public class MyWait {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
        Object object = new Object();
        synchronized (object){
    
    
            System.out.println("等待中..");
            object.wait();
            System.out.println("等待已过...");
        }
        System.out.println("main方法结束...");
    }
}

In this way, after the execution of object.wait(), it has been waiting forever, so the program must not be able to wait forever . At this time, you need to use another method to wake up notify().
Insert picture description here

2. Need to use Object.notify () method (wake up)

  • The notify method is to make the stopped thread continue to run .
  1. The notify() method should also be called in the synchronization method or synchronization block . This method is used to notify other threads that may be waiting for the object lock of the object, notify them, and make them reacquire the object lock of the object. If there are multiple threads waiting, a thread planner randomly selects a thread in the wait state.
  2. After the notify () method, the current thread will not immediately release the object lock , until the thread execution notify () method of executing the program , which is then synchronized block exit will release the object lock .

3. Demonstration of blocking queue code

Blocking queue: ArrayBlockingQueue class

package com.zg;

/**
 * 采用顺序表实现的阻塞式队列
 * //1.首先解决线程安全问题:经过分析,在方法上面见synchronized;
 * //2.解决通知机制:
 * 调offer的有可能去唤醒poll,调用poll的有可能去唤醒offer
 */

/**
 * 生产者只调用offer
 * 消费者只调用poll
 */
public class ArrayBlockingQueue {
    
    
    private Integer[] array = new Integer[5];
    private int size = 0;
    private int headIndex = 0;//队列中的第一个元素的下标
    private int rearIndex = 0;//队尾中,下一个可以放入元素的下标(也就是队尾元素所在下标的下一个)

    public synchronized boolean offer(Integer e) throws InterruptedException {
    
    
        //临界区开始
        while (size >= array.length){
    
    //满了
            this.wait();//Object.wait();//有可能你醒过来,条件还没有满足,因为不知道谁唤醒的,所以使用while
        }

        array[rearIndex] = e;
        rearIndex++;
        if (rearIndex == array.length){
    
    
            rearIndex = 0;
        }
        size++;

        notifyAll();//大赦天下
        //临界区结束
        return true;
    }

    public synchronized Integer poll() throws InterruptedException {
    
    
        while (size <= 0){
    
    
            wait();//有可能你醒过来,条件还没有满足,因为不知道谁唤醒的,所以使用while
        }

        Integer e = array[headIndex];
        headIndex++;
        if (headIndex == array.length){
    
    
            headIndex = 0;
        }
        size--;

        notifyAll();//大赦天下
        return e;
    }
}

Producer-consumer class: QueueDemo class

package com.zg;

public class QueueDemo {
    
    
    static ArrayBlockingQueue queue = new ArrayBlockingQueue();

    //生产者
    static class Producer extends Thread{
    
    
        @Override
        public void run() {
    
    
            setName("生产者");
           while(true){
    
    
               try {
    
    
                   queue.offer(1);
               } catch (InterruptedException e) {
    
    
                   e.printStackTrace();
               }
           }
        }
    }


    //消费者
    static class Consumer extends Thread{
    
    
        @Override
        public void run() {
    
    
            setName("消费者");
            try {
    
    
                queue.poll();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
    
    
        for (int i = 0;i < 5;i++){
    
    
            Thread t1 = new Producer();//生产者
            t1.start();
        }

        for (int i = 0;i < 5;i++){
    
    
            Thread t = new Consumer();//消费者
            t.start();
        }
    }
}

Guess you like

Origin blog.csdn.net/qq_45665172/article/details/113818222