欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 旅游 > LRU 和 DiskLRU实现相册缓存器

LRU 和 DiskLRU实现相册缓存器

2025/6/7 6:33:29 来源:https://blog.csdn.net/jacky128256/article/details/148481115  浏览:    关键词:LRU 和 DiskLRU实现相册缓存器

我是写Linux后端的(golang、c++、py),后端缓存算法通常是指的是内存里面的lru、或diskqueue,都是独立使用。 很少有用内存lru与disklru结合的场景需求。近段时间研究android开发,里面有一些设计思想值得后端学习。

写这篇文章的原因:
看到了android开发里面的一个片段
在这里插入图片描述

于是在画板里面手绘下图:
在这里插入图片描述

为了简化测试,用Python编程语言实现

import tkinter as tk
from tkinter import ttk, messagebox
from PIL import Image, ImageTk, ImageOps
import requests
from io import BytesIO
import threading
import queue
from functools import lru_cache
from diskcache import Cache
import os# 配置缓存
CACHE_DIR = "image_cache"
os.makedirs(CACHE_DIR, exist_ok=True)
disk_cache = Cache(CACHE_DIR)  # 磁盘缓存(自动管理容量)@lru_cache(maxsize=5)  # LRU缓存(仅记录URL)
def get_from_lru(url):passclass ImageLoader:def __init__(self):self.queue = queue.Queue()self.thread = threading.Thread(target=self._worker, daemon=True)self.thread.start()def load(self, url, callback):self.queue.put((url, callback))def _worker(self):while True:url, callback = self.queue.get()data = Nonecache_type = "error"# 检查LRUif get_from_lru.cache_info().currsize > 0:data = disk_cache.get(url)if data:cache_type = "lru"# 检查磁盘if not data:data = disk_cache.get(url)if data:cache_type = "disk"get_from_lru(url)  # 更新LRU标记# 网络加载if not data:try:res = requests.get(url, timeout=10)res.raise_for_status()data = res.contentcache_type = "network"disk_cache.set(url, data)  # 自动处理容量限制get_from_lru(url)except Exception as e:callback(None, cache_type)continue# 返回结果try:img = Image.open(BytesIO(data))callback(img, cache_type)except:callback(None, "error")class ImageViewerApp:def __init__(self, root):self.root = rootself.root.title("图片查看器")self.urls = [f"https://picsum.photos/seed/img{i}/800/600" for i in range(1, 11)]self.current = 0self.loader = ImageLoader()self._create_widgets()def _create_widgets(self):frame = ttk.Frame(self.root, padding=10)frame.pack(fill=tk.BOTH, expand=True)# 图片显示区域self.img_label = ttk.Label(frame)self.img_label.pack(fill=tk.BOTH, expand=True, padx=10, pady=10)# 导航按钮btn_frame = ttk.Frame(frame)btn_frame.pack(fill=tk.X, pady=5)self.prev_btn = ttk.Button(btn_frame, text="◀ 上一张", command=self.prev_image)self.prev_btn.pack(side=tk.LEFT, padx=5)self.next_btn = ttk.Button(btn_frame, text="下一张 ▶", command=self.next_image)self.next_btn.pack(side=tk.RIGHT, padx=5)# 缓存状态self.status_label = ttk.Label(frame, text="缓存状态: LRU(0/5), 磁盘(0/8)")self.status_label.pack(fill=tk.X, pady=2)# 加载指示器self.loading = ttk.Label(self.img_label, text="加载中...", font=("SimHei", 12))def _load_image(self, index):self.current = indexurl = self.urls[index]self.status_label.config(text="加载中...")self.loading.place(relx=0.5, rely=0.5, anchor="center")self.prev_btn.config(state=tk.DISABLED)self.next_btn.config(state=tk.DISABLED)self.loader.load(url, self._on_loaded)def _on_loaded(self, img, cache_type):self.root.after(0, lambda: self._update_display(img, cache_type))def _update_display(self, img, cache_type):self.loading.place_forget()self.prev_btn.config(state=tk.NORMAL)self.next_btn.config(state=tk.NORMAL)if img:# 调整图片大小max_w = self.img_label.winfo_width() - 20max_h = self.img_label.winfo_height() - 20img = ImageOps.contain(img, (max_w or 500, max_h or 400))self.photo = ImageTk.PhotoImage(img)self.img_label.config(image=self.photo)# 更新缓存状态lru = get_from_lru.cache_info().currsizedisk = len(disk_cache)self.status_label.config(text=f"缓存状态: LRU({lru}/5) [{cache_type.upper()}], 磁盘({disk}/8)")else:messagebox.showerror("错误", "无法加载图片")def prev_image(self):self._load_image((self.current - 1) % 10)def next_image(self):self._load_image((self.current + 1) % 10)if __name__ == "__main__":root = tk.Tk()root.geometry("800x600")app = ImageViewerApp(root)app._load_image(0)root.mainloop()

测试效果:
经过缓存的图片从内存或文件加载,速度快了很多。 用空间换时间_
在这里插入图片描述
在这里插入图片描述

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词