ASP.NET Core 中的 ObjectPool 对象重用(一)
前言
对象池是一种设计模式,一个对象池包含一组已经初始化过且可以使用的对象,而可以在有需求时创建和销毁对象。池的对象可以从池中取得对象,对其进行操作处理,并在不需要时归还给池子而非直接销毁他,他是一种特殊的工厂对象。
若初始化、实例化的代价高,且有需求需要经常实例化,但每次实例化的数量较小的情况下,使用对象池可以过得显著的性能提升。从池子中取得对象的时间是可测的,但新建一个实际所需要的时间是不确定的。
对象池的优势
说到池我们就会联想到很多的概念,如线程池、数据库连接池、内存池等等在多线程设计中可以通过池化机制来进行对象的复用从而提高性能。池的核心优势是 对象复用,这样就免去了对象创建的开销以及回收产生的内容开销,尤其创建对象这是一个很耗时的事情比如IO操作.
拿我们最常见的线程池为例,线程这个对象是可以复用的,程序要执行的任务,这些任务可以交给复用的线程来处理,而线程池创建恰恰又是一个比较耗时的操作,我们通过线程对象的池化技术达到复用线程的目的。

ConcurrentBag实现对象池
池化中需要注意的是多线程中保证线程安全,.NET Framework 4 引入了 System.Collections.Concurrent 命名空间,其中包含多个线程安全且可缩放的集合类。 多个线程可以安全高效地从这些集合添加或删除项,而无需在用户代码中进行其他同步。 编写新代码时,只要将多个线程同时写入到集合时,就使用并发集合类。
ObjectPool
- Get方法用于从对象池获取到可用对象,如果对象不可用则创建对象并返回出来
- Return方法用户将对象返回到对象池
public class ObjectPool<T>
{
private ConcurrentBag<T> _object;
private Func<T> _objectGenerator;
public ObjectPool(Func<T> objectGenerator) {
_object = new ConcurrentBag<T>();
_objectGenerator = objectGenerator;
}
/// <summary>
/// 取出
/// </summary>
/// <returns></returns>
public T CheckOut() {
T item;
if (_object.TryTake(out item)) return item;
return _objectGenerator();
}
/// <summary>
/// 归还
/// </summary>
/// <param name="obj"></param>
public void CheckIn(T obj) {
_object.Add(obj);
}
}
测试
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.CheckOut();
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.CheckIn(mc);
if (cts.Token.IsCancellationRequested)
loopState.Stop();
});
Console.WriteLine("Press the Enter key to exit.");
Console.ReadLine();
cts.Dispose();
}
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();
}
}
}
这是一个简单的对象池实现,在实际的场景中还需要考虑最小值,最大值,异常处理等等
总结
在创建资源时会消耗一定的系统资源,尤其在及其复杂的结构中效果相对来说是挺明显的,再加上频繁的创建,实例化消耗的资源是很昂贵的.对象池对这些提成是相当有帮助的.
并非任何情况下都需要使用对象池,在复用生成某种对象的操作成为影响性能因素的时候,才适合采用对象池。如果对象池提成性能提高并不重要的话,还是建议不采用对象池,保持代码简单.
参考
https://zh.m.wikipedia.org/zh-cn/%E5%AF%B9%E8%B1%A1%E6%B1%A0%E6%A8%A1%E5%BC%8F
ASP.NET Core 中的 ObjectPool 对象重用(一)的更多相关文章
- ASP.NET Core 中的 ObjectPool 对象重用(二)
前言 上一篇文章主要介绍了ObjectPool的理论知识,再来介绍一下Microsoft.Extensions.ObjectPool是如何实现的. 核心组件 ObjectPool ObjectPool ...
- ASP.NET Core中如何针对一个使用HttpClient对象的类编写单元测试
原文地址: How to unit test a class that consumes an HttpClient with IHttpClientFactory in ASP.NET Core? ...
- ASP.NET CORE 中使用AutoMapper进行对象映射
ASP.NET CORE 中使用AutoMapper进行对象映射 1.什么是AutoMapper? AutoMapper是基于对象到对象约定的映射工具,常用于(但并不仅限制于)把复杂的对象模型转为DT ...
- ASP.NET Core中的依赖注入(1):控制反转(IoC)
ASP.NET Core在启动以及后续针对每个请求的处理过程中的各个环节都需要相应的组件提供相应的服务,为了方便对这些组件进行定制,ASP.NET通过定义接口的方式对它们进行了"标准化&qu ...
- [译]ASP.NET Core中使用MediatR实现命令和中介者模式
作者:依乐祝 原文地址:https://www.cnblogs.com/yilezhu/p/9866068.html 在本文中,我将解释命令模式,以及如何利用基于命令模式的第三方库来实现它们,以及如何 ...
- Asp.net core中的依赖注入
使用服务 在Asp.net core的Controller中,可以通过如下两种方式获取系统注入的服务: 构造函数 可以直接在构造函数中传入所依赖的服务,这是非常常见的DI注入方式. public Va ...
- (6)ASP.NET Core 中使用IHttpClientFactory发出HTTP请求
1.HttpClient类使用存在的问题 HttpClient类的使用所存在的问题,百度搜索的文章一大堆,好多都是单纯文字描述,让人感觉不太好理解,为了更好理解HttpClient使用存在的问题,下面 ...
- ASP.NET Core 中的那些认证中间件及一些重要知识点
前言 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(一,二,三)奠定一下基础. 有关于 Authentication 的知识太广,所以本篇介绍几个在 A ...
- Asp.net Core中使用Session
前言 2017年就这么悄无声息的开始了,2017年对我来说又是特别重要的一年. 元旦放假在家写了个Asp.net Core验证码登录, 做demo的过程中遇到两个小问题,第一是在Asp.net Cor ...
随机推荐
- python编译器的安装和pycharm的安装
python编译器的安装 进入官网https://www.python.org/,根据提示安装 安装python编译器 pychram安装 下载地址: https://www.jetbrains.co ...
- django-表单之创建表单(一)
1.在book app目录下新建一个forms.py,并加入 from django import forms class RegisterForms(forms.Form): # test=form ...
- docker-compose下的java应用启动顺序两部曲之一:问题分析
在docker-compose编排多个容器时,需要按实际情况控制各容器的启动顺序,本文是<docker-compose下的java应用启动顺序两部曲>的第一篇,文中会分析启动顺序的重要性, ...
- mysql 主从同步(转)
教程开始:一.安装MySQL 说明:在两台MySQL服务器192.168.21.169和192.168.21.168上分别进行如下操作,安装MySQL 5.5.22 二.配置MySQL主服务器(19 ...
- Flask:第一个Flask项目
在上一篇文章:Flask:项目的准备工作中,我写了flask项目的准备工作,不清楚创建flask项目需要做哪些准备的朋友可以点击链接看看 1.最简单的Flask项目 代码: from flask im ...
- JVM参数及调优
## 3.2.1 JVM参数及调优 ### 调优基本概念 在调整JVM性能时,通常有三个组件需要考虑:1. 堆大小调整2. 垃圾收集器调整3. JIT编译器 大多数调优选项都与调整堆大小和选择合适的垃 ...
- 学习笔记03http协议
1.浏览器就是一个sokect客户端,使用http协议与服务器进行交流.http请求:请求头:(请求方法)sp(url)sp http/1.x <cr><lf>(通用头类型名) ...
- JDK安装脚本
JDK@Python脚本代码如下(JDK1.8.0_31) # -*- coding: utf-8 -*- # !/usr/bin/env python # @Time : 2018/1/2 18:0 ...
- java数组、字符串拼接
1. 数组实现拼接 int[] arr ={11,22,33,44,55,66}; System.out.print("["); for (int i = 0; i <arr ...
- javascript 字符串转化成函数执行
javascript 字符串转化成函数执行<pre>function func_abc(){ alert('a');}var str = "func_abc";eval ...