当前位置: 首页 > news >正文

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()

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

http://www.lqws.cn/news/175033.html

相关文章:

  • 使用 Python 自动化 Word 文档样式复制与内容生成
  • LeetCode 热题 100 34. 在排序数组中查找元素的第一个和最后一个位置
  • 3 个优质的终端 GitHub 开源工具
  • vue+elementUI+springboot实现文件合并前端展示文件类型
  • 【推荐算法】DeepFM:特征交叉建模的革命性架构
  • jmeter之导出接口
  • 【JMeter】后置处理器 - 提取器
  • Jmeter如何进行多服务器远程测试?
  • Python应用break初解
  • 数据结构之LinkedList
  • 哈希(Hash)
  • scikit-learn机器学习
  • MySQL数据库基础(二)———数据表管理
  • 【ubuntu】虚拟机安装配置,sh脚本自动化,包含 apt+时间同步+docker+mysql+redis+pgsql
  • git提交代码和解决冲突修复bug
  • 关于Web安全:8. Web 攻击流量分析与自动化
  • figma MCP + cursor如何将设计稿生成前端页面
  • 【React】useId
  • 基于ReAction范式的问答系统实现demo
  • 如何以 9 种方式将照片从手机传输到笔记本电脑
  • 青少年编程与数学 01-011 系统软件简介 05 macOS操作系统
  • 第二十八章 RTC——实时时钟
  • WebRTC源码线程-1
  • 【大模型LLM学习】Flash-Attention的学习记录
  • 永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
  • 2.1 Windows编译环境介绍
  • Go 中 map 的双值检测写法详解
  • C语言字符数组输入输出方法大全(附带实例)
  • C#报错 iText.Kernel.Exceptions.PdfException: ‘Unknown PdfException
  • 20N60-ASEMI太阳能逆变器专用20N60