当前位置:网站首页>LeetCode-1188. Designing finite blocking queues

LeetCode-1188. Designing finite blocking queues

2022-06-29 15:17:00 Border wanderer

Implement a thread safe limited blocking queue with the following methods :

BoundedBlockingQueue(int capacity)  Constructor initializes the queue , among capacity Represents the maximum queue length .
void enqueue(int element)  Add one at the head of the team element. If the queue is full , The calling thread is blocked until the queue is not full .
int dequeue()  Returns the end of queue element and removes it from the queue . If the queue is empty , The calling thread is blocked until the queue is not empty .
int size()  Returns the number of elements in the current queue .
Your implementation will be accessed simultaneously by multiple threads for testing . Each thread is either a call only enqueue Method's producer thread , Or one that just calls dequeue Method .size Method will be called after each test case .

Please do not use the built-in limited blocking queue implementation , Otherwise, the interview will not pass .

Example 1:

Input :
1
1
["BoundedBlockingQueue","enqueue","dequeue","dequeue","enqueue","enqueue","enqueue","enqueue","dequeue"]
[[2],[1],[],[],[0],[2],[3],[4],[]]

Output :
[1,0,2,2]

explain :
Number of producer threads = 1
Number of consumer threads = 1

BoundedBlockingQueue queue = new BoundedBlockingQueue(2);   // Use capacity = 2 Initialize queue .

queue.enqueue(1);   // The producer thread will 1 Insert queue .
queue.dequeue();    // Consumer thread call dequeue And back to 1 .
queue.dequeue();    // Because the queue is empty , Consumer thread blocked .
queue.enqueue(0);   // The producer thread will 0 Insert queue . The consumer thread is unblocked and 0 Pop up the queue and return .
queue.enqueue(2);   // The producer thread will 2 Insert queue .
queue.enqueue(3);   // The producer thread will 3 Insert queue .
queue.enqueue(4);   // The producer thread has reached the maximum queue length 2 And blocked .
queue.dequeue();    // The consumer thread will 2 Eject from the queue and return . The producer thread unblocks and 4 Insert queue .
queue.size();       // There are also 2 Elements .size() Method is invoked at the end of each test case .
 

Example 2:

Input :
3
4
["BoundedBlockingQueue","enqueue","enqueue","enqueue","dequeue","dequeue","dequeue","enqueue"]
[[3],[1],[0],[2],[],[],[],[3]]

Output :
[1,0,2,1]

explain :
Number of producer threads = 3
Number of consumer threads = 4

BoundedBlockingQueue queue = new BoundedBlockingQueue(3);   // Use capacity = 3 Initialize queue .

queue.enqueue(1);   // Producer thread P1 take 1 Insert queue .
queue.enqueue(0);   // Producer thread P2 take 0 Insert queue .
queue.enqueue(2);   // Producer thread P3 take 2 Insert queue .
queue.dequeue();    // Consumer thread C1 call dequeue.
queue.dequeue();    // Consumer thread C2 call dequeue.
queue.dequeue();    // Consumer thread C3 call dequeue.
queue.enqueue(3);   // One of the producer threads will 3 Insert queue .
queue.size();       // There are also 1 Elements .

Because the producer / The number of consumer threads may be greater than 1 , We don't know how threads are scheduled by the operating system , Even if the input seems to imply order . So any output [1,0,2] or [1,2,0] or [0,1,2] or [0,2,1] or [2,0,1] or [2,1,0] Are acceptable .
 

Tips :

1 <= Number of Prdoucers <= 8
1 <= Number of Consumers <= 8
1 <= size <= 30
0 <= element <= 20
 enqueue Number of calls   Greater than or equal to  dequeue  Number of calls .
 enque, deque and  size  At most called  40  Time

#include <iostream>
#include <queue>
#include <mutex>
#include <condition_variable>
using namespace std;
class BoundedBlockingQueue {
public:
    BoundedBlockingQueue(int capacity) {
        cap = capacity;
    }

    void enqueue(int element) {
        std::unique_lock<mutex> uq(mtx);

        /*  The queue is full , wait for  */
        cv.wait(uq, [=]() {
            return (m_q.size() < cap);
            });

        m_q.push(element);
        cv.notify_one();
    }

    int dequeue() {
        std::unique_lock<mutex> uq(mtx);

        /*  The queue is empty , wait for  */
        cv.wait(uq, [=]() {
            return (!m_q.empty());
            });

        int ret = m_q.front();
        m_q.pop();

        cv.notify_one();
        return ret;
    }

    int size() {
        std::unique_lock<mutex> uq(mtx);
        return m_q.size();
    }
private:
    int cap;
    condition_variable cv;
    mutex mtx;
    queue<int> m_q;
};

原网站

版权声明
本文为[Border wanderer]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/180/202206291449127718.html