2023字节面试题——实现能定期回收旧条目的LRU缓存

这个手撕的原题是leetcode的LRU,主要是对std::chrono的使用,在原题LRU的基础上多加一个函数定期执行,然后一把大锁实现互斥访问。

C++参考代码如下:

#include <iostream>
#include <thread>
#include <chrono>
#include <vector>
#include <mutex>
#include <unordered_map>
#include <string>

#define time_point std::chrono::system_clock::time_point
#define now() std::chrono::system_clock::now()

struct Node {
    int key, value;
    time_point time;
    Node *prev, *next;
    Node(){}
    Node(int k, int v){key = k; value = v; prev = nullptr; next = nullptr;}
};

class Cache {
private:
    Node *head, *tail;
    int size = 0, capacity = 0;
    std::unordered_map<int, Node*> map;
    std::mutex mutex;
    int timegap = 0;
    int scangap = 0;
public:
    Cache (int capacity, int tg, int sg) {
        this->capacity = capacity;
        timegap = tg;
        scangap = sg;
        head = new Node();
        tail = new Node();
        head->prev = nullptr;
        tail->next = nullptr;
        head->next = tail;
        tail->prev = head;
    }

    int getScangap() {
        return this->scangap;
    }

    int put(int key, int value) {
        mutex.lock();
        if (map.find(key) == map.end()) {
            Node *node = new Node();
            node->key = key;
            node->value = value;
            map[key] = node;
            if (size == capacity) {
                Node *last = tail->prev;
                last->prev->next = tail;
                tail->prev = last->prev;
                map.erase(last->key);
                delete last;
            } else {
                size++;
            }
            head->next->prev = node;
            node->next = head->next;
            head->next = node;
            node->prev = head;
            node->time = now();
        } else {
            Node *node = map[key];
            node->value = value;
            if (node == head->next) {
                mutex.unlock();
                return 1;
            }
            node->prev->next = node->next;
            node->next->prev = node->prev;
            node->prev = nullptr;
            node->next = nullptr;
            head->next->prev = node;
            node->next = head->next;
            node->prev = head;
            head->next = node;
            node->time = now();
        }
        mutex.unlock();
        return 1;
    }

    int get(int key) {
        mutex.lock();
        if (map.find(key) == map.end()) {
            mutex.unlock();
            return -1;
        }
        Node *node = map[key];
        node->prev->next = node->next;
        node->next->prev = node->prev;
        node->prev = nullptr;
        node->next = nullptr;
        node->next = head->next;
        head->next->prev = node;
        node->prev = head;
        head->next = node;
        int res = node->value;
        node->time = now();
        mutex.unlock();
        return res;
    }

    int clear() {
        mutex.lock();
        Node *node = head->next;
        while (node != tail) {
            time_point timenow = now();
            if (std::chrono::duration_cast<std::chrono::milliseconds>(timenow - node->time).count() > timegap) {
                node->prev->next = node->next;
                node->next->prev = node->prev;
                map.erase(node->key);
                delete node;
            }
            node = node->next;
        }
        mutex.unlock();
        return 0;
    }
};

int main() {
    Cache cache{5, 5000, 5000};
    std::thread job1([&cache](){
        while(true) {
            cache.clear();
            std::this_thread::sleep_for(std::chrono::milliseconds(cache.getScangap()));
        }
    });
    std::thread job2([&cache](){
        while (true) {
            std::string cmd;
            int key, value;
            std::cin>>cmd;
            if (cmd == "get") {
                std::cin>>key;
                std::cout<<cache.get(key)<<'\n';
            } else {
                std::cin>>key>>value;
                std::cout<<cache.put(key, value)<<'\n';
            }
        }
    });
    job1.join();
    job2.join();
    return 0;
}

 

posted @ 2023-12-29 11:01  宇宙之母蔡依林  阅读(15)  评论(0)    收藏  举报