使用 ConcurrentBag 创建目标池
程序员文章站
2022-05-27 23:13:08
...
本示例演示如何使用并发包来实现对象池。 在需要某个类的多个实例并且创建或销毁该类的成本很高的情况下,对象池可以改进应用程序性能。 客户端程序请求新对象时,对象池先尝试提供一个已创建并返回到该池的对象。 仅在没有可用对象时,才会创建一个新对象。
ConcurrentBag<T> 用于存储对象,因为它支持快速插入和删除,特别是在同一线程既添加又删除项时。 本示例可进一步扩充为以包数据结构实现的 IProducerConsumerCollection<T> 为依据生成,就像 ConcurrentQueue<T> 和 ConcurrentStack<T> 一样。
using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; namespace ObjectPoolExample { public class ObjectPool<T> { private ConcurrentBag<T> _objects; private Func<T> _objectGenerator; public ObjectPool(Func<T> objectGenerator) { if (objectGenerator == null) throw new ArgumentNullException("objectGenerator"); _objects = new ConcurrentBag<T>(); _objectGenerator = objectGenerator; } public T GetObject() { T item; if (_objects.TryTake(out item)) return item; return _objectGenerator(); } public void PutObject(T item) { _objects.Add(item); } } class Program { static void Main(string[] args) { CancellationTokenSource cts = new CancellationTokenSource(); // Create an opportunity for the user to cancel. Task.Run(() => { if (Console.ReadKey().KeyChar == 'c' || Console.ReadKey().KeyChar == 'C') cts.Cancel(); }); ObjectPool<MyClass> pool = new ObjectPool<MyClass>(() => new MyClass()); // Create a high demand for MyClass objects. Parallel.For(0, 1000000, (i, loopState) => { MyClass mc = pool.GetObject(); Console.CursorLeft = 0; // This is the bottleneck in our application. All threads in this loop // must serialize their access to the static Console class. Console.WriteLine("{0:####.####}", mc.GetValue(i)); pool.PutObject(mc); if (cts.Token.IsCancellationRequested) loopState.Stop(); }); Console.WriteLine("Press the Enter key to exit."); Console.ReadLine(); cts.Dispose(); } } // A toy class that requires some resources to create. // You can experiment here to measure the performance of the // object pool vs. ordinary instantiation. class MyClass { public int[] Nums { get; set; } public double GetValue(long i) { return Math.Sqrt(Nums[i]); } public MyClass() { Nums = new int[1000000]; Random rand = new Random(); for (int i = 0; i < Nums.Length; i++) Nums[i] = rand.Next(); } } }
上一篇: 设计模式之策略模式
推荐阅读
-
Java多线程创建方式和线程池的使用方法
-
笔记:线程池的创建及使用
-
Python 使用 PyMysql、DBUtils 创建连接池,提升性能
-
荐 灵活使用线程池 & 创建用户账号信息SQL数据库--社交APP-笔记整理
-
使用 ConcurrentBag 创建目标池
-
使用 ConcurrentBag 创建目标池
-
javascript 构建一个xmlhttp对象池合理创建和使用xmlhttp对象_javascript技巧
-
spring创建项目xml文件的配置以及使用spring+c3p0连接池+jsp、servlet+elementUI+Vue简单实现学生管理系统的增删改查
-
我会手动创建线程,为什么让我使用线程池?
-
使用Executors创建线程池的思考