全球彩票平台_全球彩票注册平台|官网下载地址

热门关键词: 全球彩票平台,全球彩票注册平台,全球彩官网下载地址

listview异步图片加载优化,爬虫学习笔记

[爬虫学习笔记]MemoryCache缓存的用法学习,memorycache

         在完成了DNS解析模块之后,我意识到了DNS缓存机制也很有必要。在Redis,Memcache,和.Net自带的Cache之间,考虑到部署问题,最终选择了后者,之前在学习Web及开发的过程中用过System.Web.Caching.Cache这个类库,但是这次的爬虫程序我打算部署为桌面软件,所以选用了System.Runtime.Caching.MemoryCache(后期如有必要也会加入System.Web.Caching.Cache来适配Web端程序)。          MemoryCache的使用网上介绍的不多,不过这个是.NET4.0新引入的缓存对象,估计主要是替换原来企业库的缓存模块,使得.NET的缓存可以无处不在,而不用基于特定的Windows版本上使用。          出于方便考虑,我们将不再实例化新的MemoryCache对象,只对MemoryCache的默认示例Memory.Default进行增删查操作。 

   基础篇    增加:    var item = new CacheItem("习大大", "两学一做");
var policy = new CacheItemPolicy();
policy.SlidingExpiration = new TimeSpan(500);
//插入一条key为"习大大",value为"两学一做",500毫秒后自动销毁的缓存
MemoryCache.Default.Add(item, policy);
//重新设置policy的过期时间为当前时间 十分钟
policy.AbsoluteExpiration = DateTimeOffset.Now   TimeSpan.FromMinutes(10);
//注意,如果要使用Sliding时间,则Absolute必须为DateTimeOffset.MaxValue,反之,则Sliding必须为TimeSpan.Zero
policy.SlidingExpiration = TimeSpan.Zero;
//重新插入,覆盖前一条数据
MemoryCache.Default.Add(item, policy);

注意,如果要使用Sliding时间,则Absolute必须为DateTimeOffset.MaxValue,反之,则Sliding必须为TimeSpan.Zero 

  查询:

  缓存对象类似于字典集,查询可以直接采用memoryCache[key]来进行,例如我们查询一下前面插入的那条数据:


    var idea = MemoryCache.Default["习大大"];

  移除:

  参数

key:要移除的缓存项的唯一标识符。

regionName:缓存中的一个添加了缓存项的命名区域。不要为该参数传递值。默认情况下,此参数为null,因为 MemoryCache 类未实现区域。

      在完成了DNS解析模块之后,我意识到了DNS缓存机制也很有必要。在Redis,Memcache,和.Net自带的Cache之间,考虑到部署问题,最终选择了后者,之前在学习Web及开发的过程中用过System.Web.Caching.Cache.aspx)这个类库,但是这次的爬虫程序我打算部署为桌面软件,所以选用了System.Runtime.Caching.MemoryCache(后期如有必要也会加入System.Web.Caching.Cache来适配Web端程序)。

      MemoryCache的使用网上介绍的不多,不过这个是.NET4.0新引入的缓存对象,估计主要是替换原来企业库的缓存模块,使得.NET的缓存可以无处不在,而不用基于特定的Windows版本上使用。

      出于方便考虑,我们将不再实例化新的MemoryCache对象,只对MemoryCache的默认示例Memory.Default进行增删查操作。

基础篇

增加:

图片 1

增加缓存需要提供两个参数,CacheItem类表示缓存中的单个缓存项,

构造函数:
CacheItem(String, Object, String)            用缓存项的指定键、值和区域初始化新的 CacheItem 实例。

三个参数分别为:键、值和区域。

CacheItemPolicy类则表示缓存项的过期信息,只含有默认的构造函数。

增加一条缓存:

var item = new CacheItem("习大大", "两学一做");
var policy = new CacheItemPolicy();
policy.SlidingExpiration = new TimeSpan(500);
//插入一条key为"习大大",value为"两学一做",500毫秒后自动销毁的缓存
MemoryCache.Default.Add(item, policy);
//重新设置policy的过期时间为当前时间 十分钟
policy.AbsoluteExpiration = DateTimeOffset.Now   TimeSpan.FromMinutes(10);
//注意,如果要使用Sliding时间,则Absolute必须为DateTimeOffset.MaxValue,反之,则Sliding必须为TimeSpan.Zero
policy.SlidingExpiration = TimeSpan.Zero;
//重新插入,覆盖前一条数据
MemoryCache.Default.Add(item, policy);

注意,如果要使用Sliding时间,则Absolute必须为DateTimeOffset.MaxValue,反之,则Sliding必须为TimeSpan.Zero 

查询:

缓存对象类似于字典集,查询可以直接采用memoryCache[key]来进行,例如我们查询一下前面插入的那条数据:

var idea = MemoryCache.Default["习大大"];

移除:

图片 2

参数

key:要移除的缓存项的唯一标识符。

regionName:缓存中的一个添加了缓存项的命名区域。不要为该参数传递值。默认情况下,此参数为null,因为 MemoryCache 类未实现区域。

返回值
Type: System.Object  如果在缓存中找到该项,则为已移除的缓存项;否则为 null。

删除前面加入的那一项:

MemoryCache.Default.Remove("习大大");

进阶篇

明白了基本的用法之后,我们就可以对它做进一步的封装,使之使用起来更为便捷:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;


namespace Crawler.Common { ///

/// 基于MemoryCache的缓存辅助类 /// public static class MemoryCacheHelper { private static readonly object _locker = new object();
public static bool Contains(string key) { return MemoryCache.Default.Contains(key); }

/// /// 获取Catch元素 /// /// 所获取的元素的类型 /// 元素的键 /// 特定的元素值 public static T Get(string key) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("不合法的key!"); if (!MemoryCache.Default.Contains(key)) throw new ArgumentException("获取失败,不存在该key!"); if (!(MemoryCache.Default[key] is T)) throw new ArgumentException("未找到所需类型数据!"); return (T)MemoryCache.Default[key]; }
/// /// 添加Catch元素 /// /// 元素的键 /// 元素的值 /// 元素过期时间(时间间隔) /// 元素过期时间(绝对时间) /// public static bool Add(string key, object value, TimeSpan? slidingExpiration = null, DateTime? absoluteExpiration = null) { var item = new CacheItem(key, value); var policy = CreatePolicy(slidingExpiration, absoluteExpiration); lock (_locker) return MemoryCache.Default.Add(item, policy); }
/// /// 移出Cache元素 /// /// 待移出元素的类型 /// 待移除元素的键 /// 已经移出的元素 public static T Remove(string key) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("不合法的key!"); if (!MemoryCache.Default.Contains(key)) throw new ArgumentException("获取失败,不存在该key!"); var value = MemoryCache.Default.Get(key); if (!(value is T)) throw new ArgumentException("未找到所需类型数据!"); return (T)MemoryCache.Default.Remove(key); }
/// /// 移出多条缓存数据,默认为所有缓存 /// /// 待移出的缓存类型 /// /// public static List RemoveAll(IEnumerable keyList = null) { if (keyList != null) return (from key in keyList where MemoryCache.Default.Contains(key) where MemoryCache.Default.Get(key) is T select (T)MemoryCache.Default.Remove(key)).ToList(); while (MemoryCache.Default.GetCount() > 0) MemoryCache.Default.Remove(MemoryCache.Default.ElementAt(0).Key); return new List(); }
/// /// 设置过期信息 /// /// /// /// private static CacheItemPolicy CreatePolicy(TimeSpan? slidingExpiration, DateTime? absoluteExpiration) { var policy = new CacheItemPolicy();
if (absoluteExpiration.HasValue) { policy.AbsoluteExpiration = absoluteExpiration.Value; } else if (slidingExpiration.HasValue) { policy.SlidingExpiration = slidingExpiration.Value; }
policy.Priority = CacheItemPriority.Default;
return policy; } } }

      在完成了DNS解析模块之后,我意识到了DNS缓存机制也很有必要。在Redis,Memcache,和.Net自带的Cache之间,考虑到部署问题,最终选择了后者,之前在学习Web及开发的过程中用过System.Web.Caching.Cache.aspx)这个类库,但是这次的爬虫程序我打算部署为桌面软件,所以选用了System.Runtime.Caching.MemoryCache(后期如有必要也会加入System.Web.Caching.Cache来适配Web端程序)。

      MemoryCache的使用网上介绍的不多,不过这个是.NET4.0新引入的缓存对象,估计主要是替换原来企业库的缓存模块,使得.NET的缓存可以无处不在,而不用基于特定的Windows版本上使用。

      出于方便考虑,我们将不再实例化新的MemoryCache对象,只对MemoryCache的默认示例Memory.Default进行增删查操作。

基础篇

增加:

图片 3

增加缓存需要提供两个参数,CacheItem类表示缓存中的单个缓存项,

构造函数:
CacheItem(String, Object, String)            用缓存项的指定键、值和区域初始化新的 CacheItem 实例。

三个参数分别为:键、值和区域。

CacheItemPolicy类则表示缓存项的过期信息,只含有默认的构造函数。

增加一条缓存:

var item = new CacheItem("习大大", "两学一做");
var policy = new CacheItemPolicy();
policy.SlidingExpiration = new TimeSpan(500);
//插入一条key为"习大大",value为"两学一做",500毫秒后自动销毁的缓存
MemoryCache.Default.Add(item, policy);
//重新设置policy的过期时间为当前时间 十分钟
policy.AbsoluteExpiration = DateTimeOffset.Now   TimeSpan.FromMinutes(10);
//注意,如果要使用Sliding时间,则Absolute必须为DateTimeOffset.MaxValue,反之,则Sliding必须为TimeSpan.Zero
policy.SlidingExpiration = TimeSpan.Zero;
//重新插入,覆盖前一条数据
MemoryCache.Default.Add(item, policy);

注意,如果要使用Sliding时间,则Absolute必须为DateTimeOffset.MaxValue,反之,则Sliding必须为TimeSpan.Zero 

查询:

缓存对象类似于字典集,查询可以直接采用memoryCache[key]来进行,例如我们查询一下前面插入的那条数据:

var idea = MemoryCache.Default["习大大"];

移除:

图片 4

参数

key:要移除的缓存项的唯一标识符。

regionName:缓存中的一个添加了缓存项的命名区域。不要为该参数传递值。默认情况下,此参数为null,因为 MemoryCache 类未实现区域。

返回值
Type: System.Object  如果在缓存中找到该项,则为已移除的缓存项;否则为 null。

删除前面加入的那一项:

MemoryCache.Default.Remove("习大大");

进阶篇

明白了基本的用法之后,我们就可以对它做进一步的封装,使之使用起来更为便捷:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;


namespace Crawler.Common { ///

/// 基于MemoryCache的缓存辅助类 /// public static class MemoryCacheHelper { private static readonly object _locker = new object();
public static bool Contains(string key) { return MemoryCache.Default.Contains(key); }

/// /// 获取Catch元素 /// /// 所获取的元素的类型 /// 元素的键 /// 特定的元素值 public static T Get(string key) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("不合法的key!"); if (!MemoryCache.Default.Contains(key)) throw new ArgumentException("获取失败,不存在该key!"); if (!(MemoryCache.Default[key] is T)) throw new ArgumentException("未找到所需类型数据!"); return (T)MemoryCache.Default[key]; }
/// /// 添加Catch元素 /// /// 元素的键 /// 元素的值 /// 元素过期时间(时间间隔) /// 元素过期时间(绝对时间) /// public static bool Add(string key, object value, TimeSpan? slidingExpiration = null, DateTime? absoluteExpiration = null) { var item = new CacheItem(key, value); var policy = CreatePolicy(slidingExpiration, absoluteExpiration); lock (_locker) return MemoryCache.Default.Add(item, policy); }
/// /// 移出Cache元素 /// /// 待移出元素的类型 /// 待移除元素的键 /// 已经移出的元素 public static T Remove(string key) { if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("不合法的key!"); if (!MemoryCache.Default.Contains(key)) throw new ArgumentException("获取失败,不存在该key!"); var value = MemoryCache.Default.Get(key); if (!(value is T)) throw new ArgumentException("未找到所需类型数据!"); return (T)MemoryCache.Default.Remove(key); }
/// /// 移出多条缓存数据,默认为所有缓存 /// /// 待移出的缓存类型 /// /// public static List RemoveAll(IEnumerable keyList = null) { if (keyList != null) return (from key in keyList where MemoryCache.Default.Contains(key) where MemoryCache.Default.Get(key) is T select (T)MemoryCache.Default.Remove(key)).ToList(); while (MemoryCache.Default.GetCount() > 0) MemoryCache.Default.Remove(MemoryCache.Default.ElementAt(0).Key); return new List(); }
/// /// 设置过期信息 /// /// /// /// private static CacheItemPolicy CreatePolicy(TimeSpan? slidingExpiration, DateTime? absoluteExpiration) { var policy = new CacheItemPolicy();
if (absoluteExpiration.HasValue) { policy.AbsoluteExpiration = absoluteExpiration.Value; } else if (slidingExpiration.HasValue) { policy.SlidingExpiration = slidingExpiration.Value; }
policy.Priority = CacheItemPriority.Default;
return policy; } } }

Listview异步加载之优化篇

摘要

MemoryCache是.Net Framework 4.0开始提供的内存缓存类,使用该类型可以方便的在程序内部缓存数据并对于数据的有效性进行方便的管理,借助该类型可以实现ASP.NET中常用的Cache类的相似功能,并且可以适应更加丰富的使用场景。在使用MemoryCache时常常有各种疑问,数据是怎么组织的?有没有可能用更高效的组织和使用方式?数据超时如何控制?为了知其所以然,本文中对于MemoryCache的原理和实现方式进行了深入分析,同时在分析的过程中学习到了许多业界成熟组件的设计思想,为今后的工作打开了更加开阔的思路

本文面向的是.net 4.5.1的版本,在后续的.net版本中MemoryCache有略微的不同,欢迎补充

文章内容较长,预计阅读时间1小时左右


MemoryCache类继承自ObjectCache抽象类,并且实现了IEnumerableIDisposable接口。跟ASP.NET常用的Cache类实现了相似的功能,但是MemoryCache更加通用。使用它的时候不必依赖于System.Web类库,并且在同一个进程中可以使用MemoryCache创建多个实例。

在使用MemoryCache的时候通常会有些疑问,这个类到底内部数据是如何组织的?缓存项的超时是如何处理的?它为什么宣传自己是线程安全的?为了回答这些问题,接下来借助Reference Source对于MemoryCache的内部实现一探究竟。

返回值

关于listview的异步加载,网上其实很多示例了,总体思想差不多,不过很多版本或是有bug,或是有性能问题有待优化。有鉴于此,本人在网上找了个相对理想的版本并在此基础上进行改造,下面就让在下阐述其原理以探索个中奥秘,与诸君共赏…

MemoryCache内部数据结构

在MemoryCache类内部,数据的组织方式跟MemoryCacheStore、MemoryCacheKey和MemoryCacheEntry这三个类有关,它们的作用分别是:

  • MemoryCacheStore:承载数据
  • MemoryCacheKey:构造检索项
  • MemoryCacheEntry:缓存内部数据的真实表现形式

MemoryCache和MemoryCacheStore的关系大致如下图所示:

图片 5

从图上可以直观的看出,一个MemoryCache实例对象可以包含多个MemoryCacheStore对象,具体有几个需要取决于程序所在的硬件环境,跟CPU数目有关。在MemoryCache的内部,MemoryCacheStore对象就像一个个的小数据库一样,承载着各种数据。所以,要理解MemoryCache内部的数据结构,就需要先理解MemoryCacheStore的地位和作用。

Type: System.Object  如果在缓存中找到该项,则为已移除的缓存项;否则为 null。

删除前面加入的那一项:

MemoryCache.Default.Remove("习大大");





  进阶篇

  明白了基本的用法之后,我们就可以对它做进一步的封装,使之使用起来更为便捷:


    using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;

namespace Crawler.Common
{
    /// <summary>
    /// 基于MemoryCache的缓存辅助类
    /// </summary>
    public static class MemoryCacheHelper
    {
        private static readonly object _locker = new object();

        public static bool Contains(string key)
        {
            return MemoryCache.Default.Contains(key);
        }


        /// <summary>
        /// 获取Catch元素
        /// </summary>
        /// <typeparam name="T">所获取的元素的类型</typeparam>
        /// <param name="key">元素的键</param>
        /// <returns>特定的元素值</returns>
        public static T Get<T>(string key)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("不合法的key!");
            if (!MemoryCache.Default.Contains(key))
                throw new ArgumentException("获取失败,不存在该key!");
            if (!(MemoryCache.Default[key] is T))
                throw new ArgumentException("未找到所需类型数据!");
            return (T)MemoryCache.Default[key];
        }

        /// <summary>
        /// 添加Catch元素
        /// </summary>
        /// <param name="key">元素的键</param>
        /// <param name="value">元素的值</param>
        /// <param name="slidingExpiration">元素过期时间(时间间隔)</param>
        /// <param name="absoluteExpiration">元素过期时间(绝对时间)</param>
        /// <returns></returns>
        public static bool Add(string key, object value, TimeSpan? slidingExpiration = null, DateTime? absoluteExpiration = null)
        {
            var item = new CacheItem(key, value);
            var policy = CreatePolicy(slidingExpiration, absoluteExpiration);
            lock (_locker)
                return MemoryCache.Default.Add(item, policy);
        }

        /// <summary>
        /// 移出Cache元素
        /// </summary>
        /// <typeparam name="T">待移出元素的类型</typeparam>
        /// <param name="key">待移除元素的键</param>
        /// <returns>已经移出的元素</returns>
        public static T Remove<T>(string key)
        {
            if (string.IsNullOrWhiteSpace(key)) throw new ArgumentException("不合法的key!");
            if (!MemoryCache.Default.Contains(key))
                throw new ArgumentException("获取失败,不存在该key!");
            var value = MemoryCache.Default.Get(key);
            if (!(value is T))
                throw new ArgumentException("未找到所需类型数据!");
            return (T)MemoryCache.Default.Remove(key);
        }

        /// <summary>
        /// 移出多条缓存数据,默认为所有缓存
        /// </summary>
        /// <typeparam name="T">待移出的缓存类型</typeparam>
        /// <param name="keyList"></param>
        /// <returns></returns>
        public static List<T> RemoveAll<T>(IEnumerable<string> keyList = null)
        {
            if (keyList != null)
                return (from key in keyList
                        where MemoryCache.Default.Contains(key)
                        where MemoryCache.Default.Get(key) is T
                        select (T)MemoryCache.Default.Remove(key)).ToList();
            while (MemoryCache.Default.GetCount() > 0)
                MemoryCache.Default.Remove(MemoryCache.Default.ElementAt(0).Key);
            return new List<T>();
        }

        /// <summary>
        /// 设置过期信息
        /// </summary>
        /// <param name="slidingExpiration"></param>
        /// <param name="absoluteExpiration"></param>
        /// <returns></returns>
        private static CacheItemPolicy CreatePolicy(TimeSpan? slidingExpiration, DateTime? absoluteExpiration)
        {
            var policy = new CacheItemPolicy();

            if (absoluteExpiration.HasValue)
            {
                policy.AbsoluteExpiration = absoluteExpiration.Value;
            }
            else if (slidingExpiration.HasValue)
            {
                policy.SlidingExpiration = slidingExpiration.Value;
            }

            policy.Priority = CacheItemPriority.Default;

            return policy;
        }
    }
}

在完成了DNS解析模块之后,我意识到了DNS缓存机制也很有必要。在Redis,Memcache,和.Net自...

        

MemoryCacheStore

该类型是MemoryCache内部真正用于承载数据的容器。它直接管理着程序的内存缓存项,既然要承载数据,那么该类型中必然有些属性与数据存储有关。其具体表现是:MemoryCache中有一个类型为HashTable的私有属性_entries,在该属性中存储了它所管理的所有缓存项。

Hashtable _entries = new Hashtable(new MemoryCacheEqualityComparer());

当需要去MemoryCache中获取数据的时候,MemoryCache所做的第一步就是寻找存储被查找key的MemoryCacheStore对象,而并非是我们想象中的直接去某个Dictionary类型或者HashTable类型的对象中直接寻找结果。

在MemoryCache中查找MemoryCacheStore的方式也挺有趣,主要的逻辑在MemoryCache的GetStore方法中,源码如下(为了理解方便增加了部分注释):

internal MemoryCacheStore GetStore(MemoryCacheKey cacheKey) {
    int hashCode = cacheKey.Hash;//获取key有关的hashCode值
    if (hashCode < 0) {
        //避免出现负数
        hashCode = (hashCode == Int32.MinValue) ? 0 : -hashCode;
    }
    int idx = hashCode & _storeMask;
    //_storeMask跟CPU的数目一致,通过&进行按位与计算获取到对应的Store
    //本处代码是.NET 4.5的样子,在.NET Framework 4.7.2版本已经改成了使用%进行取余计算,对于正整数来说实际结果是一样的。
    return _stores[idx];
}

既然可能存在多个MemoryCacheStore对象,那么就需要有一定的规则来决定每个Store中存储的内容。从源码中可以看出,MemoryCache使用的是CPU的核数作为掩码,并利用该掩码和key的hashcode来计算缓存项的归属地,确实是简单而高效。

贴张效果图先:

MemoryCacheKey

MemoryCacheKey的类功能相对比较简单,主要用于封装缓存项的key及相关的常用方法。

上文提到了MemoryCacheStore中_entries的初始化方式,在构造函数的参数是一个MemoryCacheEqualityComparer对象,这是个什么东西,又是起到什么作用的呢?

MemoryCacheEqualityComparer类实现了IEqualityComparer接口,其中便定义了哈希表中判断值相等的方法,来分析下源码:

internal class MemoryCacheEqualityComparer: IEqualityComparer {

    bool IEqualityComparer.Equals(Object x, Object y) {
        Dbg.Assert(x != null && x is MemoryCacheKey);
        Dbg.Assert(y != null && y is MemoryCacheKey);

        MemoryCacheKey a, b;
        a = (MemoryCacheKey)x;
        b = (MemoryCacheKey)y;
        //MemoryCacheKey的Key属性就是我们在获取和设置缓存时使用的key值
        return (String.Compare(a.Key, b.Key, StringComparison.Ordinal) == 0);
    }

    int IEqualityComparer.GetHashCode(Object obj) {
        MemoryCacheKey cacheKey = (MemoryCacheKey) obj;
        return cacheKey.Hash;
    }
}

从代码中可以看出,MemoryCacheEqualityComparer的真正作用就是定义MemoryCacheKey的比较方法。判断两个两个MemoryCacheKey是否相等使用的就是MemoryCacheKey中的Key属性。因此我们在MemoryCache中获取和设置相关的内容时,使用的都是对于MemoryCacheKey的相关运算结果。

图片 6

MemoryCacheEntry

此类型是缓存项在内存中真正的存在形式。它继承自MemoryCacheKey类型,并在此基础上增加了很多的属性和方法,比如判断是否超时等。

先来看下该类的整体情况:

图片 7

总的来说,MemoryCacheEntry中的属性和方法主要为三类:

  1. 缓存的内容相关,如Key、Value
  2. 缓存内容的状态相关,如State、HasExpiration方法等
  3. 缓存内容的相关事件相关,如CallCacheEntryRemovedCallback方法、CallNotifyOnChanged方法等

理解了MemoryCache中数据的组织方式后,可以帮助理解数据是如何从MemoryCache中被一步步查询得到的。

 

如何从MemoryCahe中查询数据

从MemoryCache中获取数据经历了哪些过程呢?从整体来讲,大致可以分为两类:获取数据和验证有效性。

以流程图的方式表达上述步骤如下:

图片 8

详细的步骤是这样的:

  1. 校验查询参数RegionName和Key,进行有效性判断
  2. 构造MemoryCacheKey对象,用于后续步骤查询和比对现有数据
  3. 获取MemoryCacheStore对象,缩小查询范围
  4. 从MemoryCacheStore的HashTable类型属性中提取MemoryCacheEntry对象,得到key对应的数据
  5. 判断MemoryCacheEntry对象的有效性,进行数据验证工作
  6. 处理MemoryCacheEntry的滑动超时时间等访问相关的逻辑

看到此处,不禁想起之前了解的其他缓存系统中的设计,就像历史有时会有惊人的相似性,进行了良好设计的缓存系统在某些时候看起来确实有很多相似的地方。通过学习他人的优良设计,从中可以学到很多的东西,比如接下来的缓存超时机制。

         异步加载图片基本思想:

MemoryCache超时机制

MemoryCache在设置缓存项时可以选择永久缓存或者在超时后自动消失。其中缓存策略可以选择固定超时时间和滑动超时时间的任意一种(注意这两种超时策略只能二选一,下文中会解释为什么有这样的规则)。

缓存项的超时管理机制是缓存系统(比如Redis和MemCached)的必备功能,Redis中有主动检查和被动触发两种,MemCached采用的是被动触发检查,那么内存缓存MemoryCache内部是如何管理缓存项的超时机制?

MemoryCache对于缓存项的超时管理机制与Redis类似,也是有两种:定期删除和惰性删除。

本文由全球彩票平台发布于全球彩票注册平台编程,转载请注明出处:listview异步图片加载优化,爬虫学习笔记

TAG标签: 全球彩票平台
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。