12.缓存池优化:对象上限

工业相机C#开发实战:图像缓存池设计,彻底解决GC卡顿与内存碎片 工业视觉软件的性能优化,从来不是靠什么炫技的黑科技,更多是把内存管理、资源复用这些基础工作做扎实。很多人做上位机只关注算法准不准、功能全不全,忽略了内存管理的细节,到了现场跑几天就出各种玄学卡顿。图像缓存池是很小的一个优化点,但对于高速采集场景,它是决定系统长期稳定性的关键。用几十MB的固定内存,换走GC卡顿、内存碎片这些顽疾,这笔账在工业场景里永远是划算的。 阅读详情

一、为什么要限制对象池的数量

原对象池在空闲池中没有对象时,会不断实例化新对象。
如果已经取出的对象长时间不归还,每次调用 GetObj() 都可能创建新对象,导致同类对象的数量没有上限。

  • 占用更多内存。
  • 增加场景中的对象数量。
  • 增加脚本更新、物理计算和渲染压力。
  • 大量实例化还可能引起卡顿。

二、数量上限优化的核心思想

为每一类对象设置最大数量 maxNum。
有空闲对象 → 复用空闲对象
无空闲对象 + 未达上限 → 创建新对象
无空闲对象 + 已达上限 → 抢占最早使用的对象

三、对象池的数据结构

管理器使用字典保存不同类型的对象池:

Dictionary<string, PoolData> poolDic;
  • Dictionary:整个柜子。
  • string:抽屉名称(键),也是对象类型的标识。
  • PoolData:某一类对象对应的抽屉。
    每个 PoolData 内部包含两个容器:
private Stack<GameObject> dataStack = new Stack<GameObject>();
private List<GameObject> usedList = new List<GameObject>();
  • dataStack:保存当前没有使用的对象。空闲对象
  • usedList:按开始使用的先后顺序记录正在使用的对象。使用中的对象

四、为什么同时使用 Stack 和 List

1. Stack:管理空闲对象

对象池通常不关心具体取出哪个空闲对象,所以直接取出栈顶对象即可。

dataStack.Push(obj); // 归还对象
dataStack.Pop();     // 取出对象

2. List:记录使用顺序

新投入使用的对象添加到列表尾部,符合新投入使用的,放到最后才会被复用

usedList.Add(obj);
  • usedList[0]:使用时间最久的对象。
  • 列表尾部:最近开始使用的对象。
    达到数量上限时,可以通过 usedList[0] 找到最早使用的对象并进行复用。

五、对象数量的记录

public int Count => dataStack.Count;
public int UsedCount => usedList.Count;
  • Count:当前空闲对象数量。
  • UsedCount:当前正在使用的对象数量。
    这两个属性是只读属性,外部只能读取数量,不能直接修改内部容器。

六、从对象池获取对象

public GameObject GetObj(string name, int maxNum = 50)
{
    GameObject obj;

    if (!poolDic.ContainsKey(name) ||
        (poolDic[name].Count == 0 && poolDic[name].UsedCount < maxNum))
    {
        obj = GameObject.Instantiate(Resources.Load<GameObject>(name));
        obj.name = name;

        if (!poolDic.ContainsKey(name))
            poolDic.Add(name, new PoolData(poolObj, name, obj));
        else
            poolDic[name].PushUsedList(obj);
    }
    else
    {
        obj = poolDic[name].Pop();
    }

    return obj;
}

判断条件可以拆成三种情况:

情况处理方式
不存在对应对象池创建对象,并创建对应的 PoolData
没有空闲对象,且使用数量小于上限创建新对象,并加入 usedList
存在空闲对象从 dataStack 中取出
没有空闲对象,且已经达到上限复用 usedList[0]
maxNum 的默认值为 50:
public GameObject GetObj(string name, int maxNum = 50)

调用者不传参数时,单类对象默认最多创建 50 个。

七、创建新对象

obj = GameObject.Instantiate(Resources.Load<GameObject>(name));
obj.name = name;

八、PoolData.Pop() 的两种复用方式

public GameObject Pop()
{
    GameObject obj;
    if (Count > 0)
    {
        obj = dataStack.Pop();
        usedList.Add(obj);
    }
    else
    {
        obj = usedList[0];
        usedList.RemoveAt(0);
        usedList.Add(obj);
    }
    obj.SetActive(true);
    if (PoolMgr.isOpenLayout)
        obj.transform.SetParent(null);

    return obj;
}

1. 存在空闲对象

dataStack.Pop()
       ↓
加入 usedList
       ↓
SetActive(true)

2. 已达上限且没有空闲对象

取出 usedList[0]
        ↓
从列表头部删除
        ↓
重新加入列表尾部
        ↓
作为最新使用的对象

这一过程不会创建新对象,只会更新对象的使用顺序。

九、对象回收

public void Push(GameObject obj)
{
    obj.SetActive(false);
    if (PoolMgr.isOpenLayout)
        obj.transform.SetParent(rootObj.transform);

    dataStack.Push(obj);
    usedList.Remove(obj);
}

归还对象时需要完成四件事:

  1. 使用 SetActive(false) 隐藏对象。
  2. 开启布局管理时,把对象放回对应的抽屉节点。
  3. 将对象压入 dataStack,等待下次复用。
  4. 从 usedList 中移除,表示对象已不再使用。
    管理器通过对象名称找到对应的池:
public void PushObj(GameObject obj)
{
    poolDic[obj.name].Push(obj);
}

十、对象的完整生命周期

首次获取:

GetObj
  ↓
对象池不存在
  ↓
Resources.Load + Instantiate
  ↓
加入 usedList
  ↓
开始使用

正常归还:

PushObj
  ↓
SetActive(false)
  ↓
从 usedList 移除
  ↓
压入 dataStack

再次获取:

dataStack.Pop()
  ↓
加入 usedList
  ↓
SetActive(true)
  ↓
继续使用

达到上限后的获取:

dataStack 为空
  ↓
UsedCount >= maxNum
  ↓
取出 usedList[0]
  ↓
重置并复用

十二、上限优化前后的区别

对比项无数量上限有数量上限
空闲池为空创建新对象未达上限才创建
达到最大数量继续创建复用最早使用的对象
对象数量可能持续增长基本保持在设定范围内
内存和渲染压力难以控制更容易控制
使用中对象被抢占不会达到上限时可能发生

十三、PoolData.cs

using System.Collections.Generic;
using UnityEngine;

public class PoolData
{
    // 抽屉的父物体
    private readonly GameObject objRoot;

    // 当前没有使用的对象
    private readonly Stack<GameObject> objStack = new();

    // 当前正在使用的对象
    // 越靠近列表头部,表示开始使用的时间越早
    private readonly List<GameObject> usedList = new();

    // 空闲对象数量
    public int Count => objStack.Count;

    // 使用中对象数量
    public int UsedCount => usedList.Count;

    /// <summary>
    /// 创建某一类对象对应的抽屉。
    /// 创建抽屉时产生的第一个对象正在使用,因此需要记录到 usedList 中。
    /// </summary>
    public PoolData(GameObject poolRoot, string poolName, GameObject firstUsedObj)
    {
        if (PoolMgr2.Instance.IsOpenLayout)
        {
            objRoot = new GameObject(poolName);
            objRoot.transform.SetParent(poolRoot.transform);
        }

        PushUsedList(firstUsedObj);
    }

    /// <summary>
    /// 获取对象。
    /// 有空闲对象时取出空闲对象;没有空闲对象时复用最早使用的对象。
    /// </summary>
    public GameObject Pop()
    {
        GameObject obj;

        if (Count > 0)
        {
            // 优先取出空闲对象
            obj = objStack.Pop();
            usedList.Add(obj);
        }
        else
        {
            // 没有空闲对象,说明已达到上限
            // 取出使用时间最久的对象
            obj = usedList[0];
            usedList.RemoveAt(0);

            // 重新放到尾部,表示它刚刚开始新一轮使用
            usedList.Add(obj);
        }

        if (PoolMgr2.Instance.IsOpenLayout)
        {
            obj.transform.SetParent(null);
        }

        obj.SetActive(true);
        return obj;
    }

    /// <summary>
    /// 归还对象。
    /// </summary>
    public void Push(GameObject obj)
    {
        if (obj == null)
            return;

        // 防止同一个对象被重复放入空闲栈
        if (objStack.Contains(obj))
            return;

        obj.SetActive(false);

        if (PoolMgr2.Instance.IsOpenLayout)
        {
            obj.transform.SetParent(objRoot.transform);
        }

        objStack.Push(obj);
        usedList.Remove(obj);
    }

    /// <summary>
    /// 记录一个新创建、正在使用的对象。
    /// </summary>
    public void PushUsedList(GameObject obj)
    {
        if (obj != null && !usedList.Contains(obj))
        {
            usedList.Add(obj);
        }
    }
}

十四、PoolMgr2.cs

PoolMgr2 负责创建对象、获取对象、回收对象以及管理不同类型的抽屉。

using System.Collections.Generic;
using UnityEngine;

public class PoolMgr2 : Singleton2<PoolMgr2>
{
    // 柜子:Key 是对象类型,Value 是对应的抽屉
    private readonly Dictionary<string, PoolData> poolDic = new();

    // 对象池在 Hierarchy 中的总根物体
    private GameObject poolRoot;

    // 是否开启 Hierarchy 层级整理
    public bool IsOpenLayout = true;

    private PoolMgr2()
    {
    }

    /// <summary>
    /// 从对象池获取对象。
    /// </summary>
    /// <param name="name">Resources 文件夹下的资源路径。</param>
    /// <param name="maxNum">这一类对象允许存在的最大数量。</param>
    public GameObject GetObj(string name, int maxNum = 50)
    {
        if (string.IsNullOrEmpty(name))
        {
            Debug.LogError("对象池资源路径不能为空");
            return null;
        }

        // 至少允许创建一个对象
        maxNum = Mathf.Max(1, maxNum);

        // 情况一:还没有这种对象对应的抽屉
        if (!poolDic.TryGetValue(name, out PoolData poolData))
        {
            GameObject newObj = CreateObj(name);

            if (newObj == null)
                return null;

            // PoolData 创建层级节点前,必须保证总根物体已经存在
            CreatePoolRoot();

            poolData = new PoolData(poolRoot, name, newObj);
            poolDic.Add(name, poolData);

            return newObj;
        }

        // 情况二:抽屉中存在空闲对象,直接复用
        if (poolData.Count > 0)
        {
            return poolData.Pop();
        }

        // 情况三:没有空闲对象,但还没有达到数量上限
        if (poolData.UsedCount < maxNum)
        {
            GameObject newObj = CreateObj(name);

            if (newObj == null)
                return null;

            poolData.PushUsedList(newObj);
            return newObj;
        }

        // 情况四:没有空闲对象,并且已经达到数量上限
        // Pop 会取出 usedList[0],即使用时间最久的对象
        return poolData.Pop();
    }

    /// <summary>
    /// 将对象归还到对应的对象池。
    /// </summary>
    public void PushObj(GameObject obj)
    {
        if (obj == null)
            return;

        CreatePoolRoot();

        // 正常情况下,对象对应的抽屉已经在 GetObj 时创建
        // 此判断也可以兼容不是通过 GetObj 创建、但需要放入对象池的对象
        if (!poolDic.TryGetValue(obj.name, out PoolData poolData))
        {
            poolData = new PoolData(poolRoot, obj.name, obj);
            poolDic.Add(obj.name, poolData);
        }

        poolData.Push(obj);
    }

    /// <summary>
    /// 根据资源路径加载并实例化对象。
    /// </summary>
    private GameObject CreateObj(string name)
    {
        GameObject prefab = Resources.Load<GameObject>(name);

        if (prefab == null)
        {
            Debug.LogError($"Resources 中没有找到对象:{name}");
            return null;
        }

        GameObject obj = Object.Instantiate(prefab);

        // 去掉实例化后自动添加的 (Clone),方便归还时查找对象池
        obj.name = name;
        return obj;
    }

    /// <summary>
    /// 开启布局管理时,确保 Pool 根物体存在。
    /// </summary>
    private void CreatePoolRoot()
    {
        if (IsOpenLayout && poolRoot == null)
        {
            poolRoot = new GameObject("Pool");
        }
    }

    /// <summary>
    /// 清空对象池记录,通常在切换场景时调用。
    /// </summary>
    public void ClearPool()
    {
        poolDic.Clear();

        if (poolRoot != null)
        {
            Object.Destroy(poolRoot);
            poolRoot = null;
        }
    }
}

十四、Lesson12MainTest.cs

连续点击鼠标左键获取方块。最多创建 maxNum 个方块;达到上限后,会重新使用最早获取的方块。

using UnityEngine;

public class Lesson12MainTest : MonoBehaviour
{
    [SerializeField] private string resourcePath = "Prefabs/Cube";
    [SerializeField] private int maxNum = 5;
    private void Update()
    {
        if (Input.GetMouseButtonDown(0))
        {
            GameObject obj = PoolMgr2.Instance.GetObj(resourcePath, maxNum);

            if (obj == null)
                return;

            // 对象可能是从池中取出的,也可能是被抢占的旧对象
            // 因此每次获取后都应重新设置本轮使用需要的状态
            obj.transform.position = Vector3.zero;
            obj.transform.rotation = Quaternion.identity;
        }
    }
}
wps js宏获取工作簿、工作表、单元格的值、链接转图片、单元格区域数据转二维数组、保存工作簿的常用Excel操作 wps js宏入门看这里,我写了常用的js操作Excel的方法:获取工作簿对象、获取工作表对象、获取单元格的值、链接转图片、生成条形码图片、单元格区域数据转二维数组方法、保存工作簿、弹出输入框、YesNo选择框,助你从VBA转战JS。 阅读详情

相关推荐

深入浅出CenterFusion

结合论文和代码理解CenterFusion

Untitled的专栏 5101

Java 中的 Integer 缓存池:背后的性能优化机制解析

Integer 缓存池(Integer Cache)是 JDK 内部维护的一个静态缓存,用于存储一定范围内的 Integer 对象。当我们获取这个范围内的 Integer 对象时,Java 会直接返回缓存池中已有的对象,而不是创建新的实例,从而提高内存使用效率和程序性能。Integer 缓存池本质是"享元模式(Flyweight Pattern)"的应用——通过共享细粒度对象,减少内存占用并提高性能。

jiaworld的博客 955

PointNetLK实战:5步搞定点云配准(附ModelNet40数据集训练技巧)

本文提供了一份详细的PointNetLK实战指南,帮助读者在5步内掌握点云配准技术。文章以ModelNet40数据集为例,深入讲解了环境搭建、数据预处理、模型训练与调试等核心步骤,并分享了关键的训练技巧和调参策略,旨在让开发者快速实现并应用这一高效的深度学习配准方法。

wind6的博客 461

案例分析:池化对象的应用场景12

在我们平常的编码中,通常会将一些对象保存起来,这主要考虑的是对象的创建成本。比如像线程资源、数据库连接资源或者 TCP 连接等,这类对象的初始化通常要花费比较长的时间,如果频繁地申请和销毁,就会耗费大量的系统资源,造成不必要的性能损失。并且这些对象都有一个显著的特征,就是通过轻量级的重置工作,可以循环、重复地使用。这个时候,我们就可以。在 Java 中,应用非常广泛,常见的就有数据库连接池、线程池等,本节课主讲连接池,线程池我们将在 12 课时进行介绍。

xiaoxu2022xiaoxu的博客 1522

Intel SGX Explained

计算机中最主要的资源是CPU和内存,由操作系统和虚拟管理系统等系统软件来管理这些资源。

hanqdi_的博客 3452

STM32CubeIDE离线安装芯片PACK包全攻略(附离线包下载与导入步骤)

本文详细介绍了在STM32CubeIDE中离线安装芯片PACK包的完整流程,包括官方和第三方资源获取方法、本地安装步骤及常见问题解决方案。特别针对网络隔离环境下的嵌入式开发需求,提供了实用的版本管理和自动化部署技巧,帮助开发者高效完成芯片固件支持包的离线配置。

weixin_30825581的博客 298

案例分析:池化对象的应用场景9

在我们平常的编码中,通常会将一些对象保存起来,这主要考虑的是对象的创建成本。比如像线程资源、数据库连接资源或者 TCP 连接等,这类对象的初始化通常要花费比较长的时间,如果频繁地申请和销毁,就会耗费大量的系统资源,造成不必要的性能损失。并且这些对象都有一个显著的特征,就是通过轻量级的重置工作,可以循环、重复地使用。这个时候,我们就可以。在 Java 中,应用非常广泛,常见的就有数据库连接池、线程池等,本节课主讲连接池,线程池我们将在 12 课时进行介绍。

xiaoxu2022xiaoxu的博客 1419

LabVIEW数据采集-数字I/O/计数器

labview 数据采集 数字I/O 计数器

weixin_43781045的博客 5617

案例分析:池化对象的应用场景3

在我们平常的编码中,通常会将一些对象保存起来,这主要考虑的是对象的创建成本。比如像线程资源、数据库连接资源或者 TCP 连接等,这类对象的初始化通常要花费比较长的时间,如果频繁地申请和销毁,就会耗费大量的系统资源,造成不必要的性能损失。并且这些对象都有一个显著的特征,就是通过轻量级的重置工作,可以循环、重复地使用。这个时候,我们就可以。在 Java 中,应用非常广泛,常见的就有数据库连接池、线程池等,本节课主讲连接池,线程池我们将在 12 课时进行介绍。

xiaoxu2022xiaoxu的博客 1796

别让IO口保护二极管坑了你!实测讲解单片机电流倒灌的三种典型症状与防护

本文深入解析单片机电流倒灌的三大典型症状与防护方案,重点分析STM32等单片机在ADC采样异常、系统假死和通信速率异常中的表现。通过实测数据和电路设计建议,提供从基础二极管隔离到专业隔离器件的分级防护策略,帮助工程师有效预防和解决电流倒灌问题。

weixin_29280219的博客 344

基于Python的网络拓扑图绘制

最近写论文画了许多图,在这里记录一些。当然,如果仅仅是展示性图片的话也可以使用visio,但是这里我仍然想探究一下如何使用pyhon画出美观的网络拓扑图。(1)根据邻接矩阵画出网络拓扑图(2)画出网络拓扑图,并对节点和链路进行表示,包括对节点和链路的标号,颜色区分,以及尺寸区分。

m0_53961910的博客 7093

案例分析:池化对象的应用场景13

在我们平常的编码中,通常会将一些对象保存起来,这主要考虑的是对象的创建成本。比如像线程资源、数据库连接资源或者 TCP 连接等,这类对象的初始化通常要花费比较长的时间,如果频繁地申请和销毁,就会耗费大量的系统资源,造成不必要的性能损失。并且这些对象都有一个显著的特征,就是通过轻量级的重置工作,可以循环、重复地使用。这个时候,我们就可以。在 Java 中,应用非常广泛,常见的就有数据库连接池、线程池等,本节课主讲连接池,线程池我们将在 12 课时进行介绍。

xiaoxu2022xiaoxu的博客 2917

Geneformer实战:如何用Hugging Face Transformers快速搭建单细胞转录组分类模型

本文详细介绍了如何使用Geneformer和Hugging Face Transformers快速搭建单细胞转录组分类模型。通过环境准备、数据预处理、模型加载与配置、训练Pipeline构建等步骤,帮助读者掌握基于Transformer架构的单细胞数据分析技术,提升分类准确率和效率。

rl6adventurer的博客 605

案例分析:池化对象的应用场景1

在我们平常的编码中,通常会将一些对象保存起来,这主要考虑的是对象的创建成本。比如像线程资源、数据库连接资源或者 TCP 连接等,这类对象的初始化通常要花费比较长的时间,如果频繁地申请和销毁,就会耗费大量的系统资源,造成不必要的性能损失。并且这些对象都有一个显著的特征,就是通过轻量级的重置工作,可以循环、重复地使用。这个时候,我们就可以。在 Java 中,应用非常广泛,常见的就有数据库连接池、线程池等,本节课主讲连接池,线程池我们将在 12 课时进行介绍。

xiaoxu2022xiaoxu的博客 1535

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

案例分析:池化对象的应用场景10

在我们平常的编码中,通常会将一些对象保存起来,这主要考虑的是对象的创建成本。比如像线程资源、数据库连接资源或者 TCP 连接等,这类对象的初始化通常要花费比较长的时间,如果频繁地申请和销毁,就会耗费大量的系统资源,造成不必要的性能损失。并且这些对象都有一个显著的特征,就是通过轻量级的重置工作,可以循环、重复地使用。这个时候,我们就可以。在 Java 中,应用非常广泛,常见的就有数据库连接池、线程池等,本节课主讲连接池,线程池我们将在 12 课时进行介绍。

xiaoxu2022xiaoxu的博客 1859

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

案例分析:池化对象的应用场景8

在我们平常的编码中,通常会将一些对象保存起来,这主要考虑的是对象的创建成本。比如像线程资源、数据库连接资源或者 TCP 连接等,这类对象的初始化通常要花费比较长的时间,如果频繁地申请和销毁,就会耗费大量的系统资源,造成不必要的性能损失。并且这些对象都有一个显著的特征,就是通过轻量级的重置工作,可以循环、重复地使用。这个时候,我们就可以。在 Java 中,应用非常广泛,常见的就有数据库连接池、线程池等,本节课主讲连接池,线程池我们将在 12 课时进行介绍。

xiaoxu2022xiaoxu的博客 1818

案例分析:池化对象的应用场景5

在我们平常的编码中,通常会将一些对象保存起来,这主要考虑的是对象的创建成本。比如像线程资源、数据库连接资源或者 TCP 连接等,这类对象的初始化通常要花费比较长的时间,如果频繁地申请和销毁,就会耗费大量的系统资源,造成不必要的性能损失。并且这些对象都有一个显著的特征,就是通过轻量级的重置工作,可以循环、重复地使用。这个时候,我们就可以。在 Java 中,应用非常广泛,常见的就有数据库连接池、线程池等,本节课主讲连接池,线程池我们将在 12 课时进行介绍。

xiaoxu2022xiaoxu的博客 1512

案例分析:池化对象的应用场景11

在我们平常的编码中,通常会将一些对象保存起来,这主要考虑的是对象的创建成本。比如像线程资源、数据库连接资源或者 TCP 连接等,这类对象的初始化通常要花费比较长的时间,如果频繁地申请和销毁,就会耗费大量的系统资源,造成不必要的性能损失。并且这些对象都有一个显著的特征,就是通过轻量级的重置工作,可以循环、重复地使用。这个时候,我们就可以。在 Java 中,应用非常广泛,常见的就有数据库连接池、线程池等,本节课主讲连接池,线程池我们将在 12 课时进行介绍。

xiaoxu2022xiaoxu的博客 1656

案例分析:池化对象的应用场景14

在我们平常的编码中,通常会将一些对象保存起来,这主要考虑的是对象的创建成本。比如像线程资源、数据库连接资源或者 TCP 连接等,这类对象的初始化通常要花费比较长的时间,如果频繁地申请和销毁,就会耗费大量的系统资源,造成不必要的性能损失。并且这些对象都有一个显著的特征,就是通过轻量级的重置工作,可以循环、重复地使用。这个时候,我们就可以。在 Java 中,应用非常广泛,常见的就有数据库连接池、线程池等,本节课主讲连接池,线程池我们将在 12 课时进行介绍。

xiaoxu2022xiaoxu的博客 1559

案例分析:池化对象的应用场景6

在我们平常的编码中,通常会将一些对象保存起来,这主要考虑的是对象的创建成本。比如像线程资源、数据库连接资源或者 TCP 连接等,这类对象的初始化通常要花费比较长的时间,如果频繁地申请和销毁,就会耗费大量的系统资源,造成不必要的性能损失。并且这些对象都有一个显著的特征,就是通过轻量级的重置工作,可以循环、重复地使用。这个时候,我们就可以。在 Java 中,应用非常广泛,常见的就有数据库连接池、线程池等,本节课主讲连接池,线程池我们将在 12 课时进行介绍。

xiaoxu2022xiaoxu的博客 1776

案例分析:池化对象的应用场景15

在我们平常的编码中,通常会将一些对象保存起来,这主要考虑的是对象的创建成本。比如像线程资源、数据库连接资源或者TCP连接等,这类对象的初始化通常要花费比较长的时间,如果频繁地申请和销毁,就会耗费大量的系统资源,造成不必要的性能损失。并且这些对象都有一个显著的特征,就是通过轻量级的重置工作,可以循环、重复地使用。这个时候,我们就可以。在Java中,应用非常广泛,常见的就有数据库连接池、线程池等,本节课主讲连接池,线程池我们将在12课时进行介绍。

xiaoxu2022xiaoxu的博客 1764
上一篇: 11.缓存池优化:窗口布局
下一篇: 13.缓存池优化:对象上限配置
Unity黑马王子
博客等级 码龄4年 1846粉丝 181原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值