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

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.xdnf.cn/news/12335.html

相关文章:

  • coze平台创建智能体,关于智能体后端接入的问题
  • Typeerror: cannot read properties of undefined (reading ‘XXX‘)
  • 【Linux】(1)—进程概念-④fork、僵尸进程、孤儿进程
  • 【Linux】(1)—进程概念-⑤进程调度
  • 如何把本地服务器变成公网服务器?内网ip网址转换到外网连接访问
  • 国芯思辰| AD7894的优质替代方案:SC1424模数转换器在分布式控制系统中的应用优势
  • I2C通信讲解
  • Git的由来与应用详解:从Linux内核到现代开发的革命性工具
  • Shell基础
  • 记录一次 apt-key curl导入失败的处理方式
  • 阶乘的因数
  • 算法篇 八大排序(冒泡 插入 选择 堆 希尔 快排 归并 计数)
  • Linux中INADDR_ANY详解
  • [蓝桥杯]堆的计数
  • rocketmq索引
  • 《最长公共子序列》题集
  • Educational Codeforces Round 179 (Rated for Div. 2)
  • 2025年5月月赛 乙组T1~T3
  • RPG22.处理武器碰撞
  • 所有CSS选择器
  • 2025爱分析·银行数字化应用实践报告|爱分析报告
  • 策略梯度核心:Advantage 与 GAE 原理详解
  • 苍穹外卖|学习笔记|day06
  • Day13
  • Grafana-ECharts应用讲解(玫瑰图示例)
  • 定时任务的 cron 表达式
  • OpenEuler24.03 部署RagFlow学习记录(PVE虚拟化环境)
  • 实验科学中策略的长期效应评估学习笔记
  • Day45 Python打卡训练营
  • 图像分割算法入门:从基础到FCN