• 属性缓存_使用ConcurrentDictionary替代Hashtable对多线程的对象缓存处理


      转载:https://www.cnblogs.com/wuhuacong/p/6934851.html

      在之前一段时间里面,我的基类多数使用lock和Hashtable组合实现多线程内缓存的冲突处理,不过有时候使用这两个搭配并不尽如人意,偶尔还是出现了集合已经加入的异常,对代码做多方的处理后依然如故,最后采用了.NET 4.0后才引入的ConcurrentDictionary多线程同步字典集合,问题顺利解决。

    1、使用lock和Hashtable组合实现

    在我的基类里面,构建业务对象,一般用BLLFactory<T>.Instance就可以获得对应业务对象的应用了。

    var result = BLLFactory<Customer>.Instance.FindFirst();
    Console.WriteLine(result.ToJson());

    因此使用BLLFactory<T>.Instance这个构建对象后,把它们放到HashTable里面,由于需要设计多线程冲突处理,因此需要使用lock对象来实现锁定的处理。

    HashTable表示键/值对的集合。在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似key-value的键值对,其中key通常可用来快速查找,同时key是区分大小写;value用于存储对应于key的值。Hashtable中key-value键值对均为object类型,所以Hashtable可以支持任何类型的keyvalue键值对,任何非 null 对象都可以用作键或值。

    使用这种方式,偶尔在Web端,还是出现多线程访问冲突的问题,为此我们也可以使用多线程的测试代码来进行测试重现错误,

    复制代码
                try
                {
                    List<Thread> list = new List<Thread>();
                    for (int i = 0; i < 10; i++)
                    {
                        Thread thread = new Thread(() =>
                        {
                            var result = BLLFactory<Customer>.Instance.FindFirst();
                            Console.WriteLine(result.ToJson());
                            Console.WriteLine();
                        });
    
                        list.Add(thread);
                    }
    
                    for (int i = 0; i < list.Count; i++)
                    {
                        list[i].Start();
                    }
                }
                catch(Exception ex)
                {
                    LogTextHelper.Error(ex);
                }
    复制代码

    跟踪代码得到错误信息如下所示。

    因此,从上面代码可以看到,使用lock(syncRoot)也无法出现的多线程冲突问题。

    2、使用ConcurrentDictionary替代Hashtable

    ConcurrentDictionary是.net4.0推出的一套线程安全集合里的其中一个,和它一起被发行的还有ConcurrentStack,ConcurrentQueue等类型,它们的单线程版本(线程不安全的,Queue,Stack,Dictionary)我们一定不会陌生。ConcurrentDictionary<TKey, TValue> 可由多个线程同时访问,且线程安全,用法同Dictionary很多相同,但是多了一些方法。ConcurrentDictionary 属于System.Collections.Concurrent 命名空间。

    System.Collections.Concurrent 命名空间提供多个线程安全集合类。当有多个线程并发访问集合时,应使用这些类代替 System.Collections 和 System.Collections.Generic 命名空间中的对应类型

    ConcurrentDictionary这个类提供了下面几个方法,用于对集合的处理

    复制代码
    public bool TryAdd(TKey key, TValue value)
    
    public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue)
    
    public TValue this[TKey key] { get; set; }
    
    public TValue AddOrUpdate(TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory)
        
    public TValue AddOrUpdate(TKey key, TValue addValue, Func<TKey, TValue, TValue> updateValueFactory)
    
    public TValue GetOrAdd(TKey key, TValue value)
    
    public TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory)
    复制代码

    使用ConcurrentDictionary来替代Hashtable,我们来看看BLLFactory的类的实现代码如下所示。

    复制代码
        /// <summary>
        /// 对业务类进行构造的工厂类
        /// </summary>
        /// <typeparam name="T">业务对象类型</typeparam>
        public class BLLFactory<T> where T : class
        {
            //采用ConcurrentDictionary线程安全的集合类来缓存,替代Hashtable
            private static ConcurrentDictionary<string, object> conCurrentCache = new ConcurrentDictionary<string, object>(); 
    
            /// <summary>
            /// 创建或者从缓存中获取对应业务类的实例
            /// </summary>
            public static T Instance
            {
                get
                {
                    string CacheKey = typeof(T).FullName;
    
                    return (T)conCurrentCache.GetOrAdd(CacheKey, s =>
                    {
                        var bll = Reflect<T>.Create(typeof(T).FullName, typeof(T).Assembly.GetName().Name); //反射创建,并缓存
                        return bll;
                    });
                }
            }
        } 
    复制代码

    我们可以看到代码简化了很多,而且使用前面的多线程测试代码,也顺利获取数据,不会出现异常了。

    运行代码可以顺利实现,不会出现之前使用Hashtable出现的多线程访问异常了。

    以上就是引入ConcurrentDictionary替代Hashtable对多线程的对象缓存处理,能够顺利解决问题的时候,发现其访问效率也是较之前有所提高,一举两得。

  • 相关阅读:
    Vue2.5开发去哪儿网App 城市列表开发之 Vuex实现数据共享及高级使用
    Vue2.5开发去哪儿网App 搜索功能完成
    Vue2.5开发去哪儿网App 城市列表开发之 兄弟组件间联动及列表性能优化
    Vue2.5开发去哪儿网App 城市列表开发
    Vue2.5开发去哪儿网App 首页开发
    Vue2.5开发去哪儿网App 第五章笔记 下
    Vue2.5开发去哪儿网App 第五章笔记 上
    页面基本布局的一二事
    css属性—position的使用与页面的分层介绍
    Html的本质及在web中的作用
  • 原文地址:https://www.cnblogs.com/lxhbky/p/14005070.html
Copyright © 2020-2023  润新知