设计模式-对象池模式

news2024/11/28 10:35:45
设计模式专栏

    • 模式介绍
    • 模式特点
    • 应用场景
    • 对象池模式和工厂模式的区别
    • 代码示例
      • Java实现对象池模式
      • Python实现对象池模式
    • 对象池模式在spring中的应用


模式介绍

对象池模式是一种创建型设计模式,它将对象预先创建并初始化后放入一个池中,以供其他对象使用。这种模式的主要目的是减少频繁创建和销毁对象所占用的内存空间和初始化时间。

一个对象池包含一组已经初始化并且可以使用的对象。当某个对象需要使用这些对象时,可以从池中获取一个对象,对其进行操作处理,并在使用完毕后将该对象归还给池子,而不是直接销毁。这样可以避免频繁地创建和销毁对象,提高内存管理效率。

总之,对象池模式通过预先创建和初始化对象并放入池中,使得其他对象可以重复使用这些对象,提高了内存管理效率,减少了对象的创建和销毁开销。

在这里插入图片描述

模式特点

  • 对象池模式的优点主要包括以下几点:
  1. 复用池中对象,没有分配内存和创建堆中对象的开销,没有释放内存和销毁堆中对象的开销,进而减少垃圾收集器的负担,避免内存抖动。
  2. 不必重复初始化对象状态,对于比较耗时的constructor和finalize来说非常合适。
  3. 可以避免频繁地创建和销毁对象,提高内存管理效率。
  4. 可以更好地管理和控制对象的数量,例如线程池或数据库连接池。
  • 然而,对象池模式也存在一些缺点:
  1. 增加了分配/释放对象的开销。
  2. 在并发环境中,多个线程可能同时需要获取池中对象,需要在堆数据结构上进行同步或因为锁竞争而产生阻塞,这种开销要比创建销毁对象的开销高数百倍。
  3. 由于池中对象的数量有限,势必成为一个可伸缩性瓶颈。
  4. 很难正确地设定对象池的大小,如果太小则起不到作用,如果过大,则占用内存资源高。

因此,使用对象池模式时需要根据具体情况权衡利弊,并根据应用场景选择合适的实现方式。

在这里插入图片描述

应用场景

对象池模式主要适用于以下应用场景:

  1. 资源受限的场景 :在不需要可伸缩性的环境(如CPU、内存等物理资源有限)中,如果CPU性能不够强劲或内存比较紧张,垃圾收集和内存抖动可能会造成较大影响,需要提高内存管理效率,响应性比吞吐量更为重要。
  2. 创建成本高的对象 :对于那些创建成本高的对象,可以考虑将其池化,以减少创建和销毁对象的开销。
  3. 在内存中数量受限的对象 :对于那些在内存中数量受限的对象,例如线程池或数据库连接池,使用对象池模式可以更好地管理和控制对象的数量。

在这里插入图片描述

对象池模式和工厂模式的区别

对象池模式工厂模式都是常用的设计模式,但它们有不同的应用场景和特点。

对象池模式主要适用于一些创建成本较高的对象,比如数据库连接、线程池等。在创建这些对象时,需要进行一些繁琐的初始化操作,并且创建和销毁的成本较高。通过使用对象池,我们可以重复利用这些对象,避免浪费资源,提高系统性能。

而工厂模式主要适用于需要创建不同类型对象的场景。当一个类需要创建某个类型的对象时,可以调用工厂方法来创建对象,而不是直接使用new关键字创建对象。这样可以提高代码的灵活性和可维护性,因为如果需要改变对象的创建方式,只需要修改工厂方法的实现即可,而不需要修改使用new关键字创建对象的代码。

对象池模式和工厂模式都可以提高系统性能和可伸缩性,但它们的应用场景和特点不同。在实际应用中,可以根据具体需求选择合适的设计模式。

在这里插入图片描述

代码示例

Java实现对象池模式

下面是一个简单的Java实现对象池模式的示例:

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class ObjectPool<T> {
    private final int maxPoolSize;
    private final BlockingQueue<T> pool;

    public ObjectPool(int maxPoolSize) {
        this.maxPoolSize = maxPoolSize;
        this.pool = new LinkedBlockingQueue<>(maxPoolSize);
    }

    public synchronized T acquire() throws InterruptedException {
        while (pool.isEmpty()) {
            if (pool.size() < maxPoolSize) {
                T newObj = createObject(); // 创建对象的方法,可以根据需要自定义
                pool.add(newObj); // 添加新对象到池中
            } else {
                wait(); // 等待对象可用
            }
        }
        return pool.take(); // 从池中获取对象
    }

    public synchronized void release(T obj) {
        if (pool.size() < maxPoolSize) {
            pool.add(obj); // 将对象放回池中
            notifyAll(); // 唤醒等待的线程
        } else {
            destroyObject(obj); // 销毁对象的方法,可以根据需要自定义
        }
    }

    private T createObject() {
        // 创建对象的逻辑,可以根据需要自定义
        return null;
    }

    private void destroyObject(T obj) {
        // 销毁对象的逻辑,可以根据需要自定义
    }
}

使用示例:

public class Main {
    public static void main(String[] args) throws InterruptedException {
        ObjectPool<MyObject> pool = new ObjectPool<>(5); // 创建一个最大容量为5的对象池
        for (int i = 0; i < 10; i++) {
            MyThread thread = new MyThread(pool); // 使用对象池的线程类MyThread进行任务处理
            thread.start(); // 启动线程进行任务处理
        }
    }
}

Python实现对象池模式

下面是一个Python实现对象池模式的示例:

import threading

class ObjectPool:
    def __init__(self, max_pool_size):
        self.max_pool_size = max_pool_size
        self.pool = []
        self.lock = threading.Lock()

    def acquire(self):
        with self.lock:
            while len(self.pool) == 0:
                if len(self.pool) < self.max_pool_size:
                    new_obj = self.create_object()
                    self.pool.append(new_obj)
                else:
                    threading.Condition(self.lock).wait()
            obj = self.pool.pop(0)
            return obj

    def release(self, obj):
        with self.lock:
            if len(self.pool) < self.max_pool_size:
                self.pool.append(obj)
                threading.Condition(self.lock).notify()
            else:
                self.destroy_object(obj)

    def create_object(self):
        # 创建对象的逻辑,可以根据需要自定义
        return None

    def destroy_object(self, obj):
        # 销毁对象的逻辑,可以根据需要自定义
        pass

使用示例:

if __name__ == '__main__':
    pool = ObjectPool(5) # 创建一个最大容量为5的对象池
    for i in range(10):
        thread = MyThread(pool) # 使用对象池的线程类MyThread进行任务处理
        thread.start() # 启动线程进行任务处理

在这里插入图片描述

对象池模式在spring中的应用

在Spring框架中,并没有直接实现对象池模式,但它提供了相关的支持,使得我们可以方便地实现该模式。例如,Spring的Bean生命周期管理和依赖注入特性可以用于实现自定义的对象池。此外,Spring也提供了与一些常见对象池(如数据库连接池)的集成。

具体来说,Spring中的对象池设计模式主要用于在一个池中保存特定数量的对象,并根据需要重新使用。通过这种方式,可以改善使用巨型对象的响应时间。巨型对象指的是那些构造需要很多时间的对象,例如持有数据库连接的对象。最好重用已经存在的和未获取的对象,而不是创建新对象。

在Spring中,数据库连接池不是由Spring直接实现的,而是适用于Spring工作方式的连接池,例如C3P0或Jakarta Commons DBCP连接池。这些连接池作为组件被使用时,会从池中借出对象,用它来完成一些任务并当任务完成时归还该对象。被归还的对象接着满足请求,不管是同一个组件还是其他组件的请求。

Spring中的对象池模式主要是通过集成第三方库来使用和管理对象池,以提高系统的性能和响应时间。

在这里插入图片描述

设计模式-适配器模式

设计模式-工厂模式

设计模式-代理模式

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1341481.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

python如何读取被压缩的图像

读取压缩的图像数据&#xff1a; PackBits 压缩介绍&#xff1a; CCITT T.3 压缩介绍&#xff1a; 读取压缩的图像数据&#xff1a; 在做图像处理的时候&#xff0c;平时都是使用 函数io.imread() 或者是 函数cv2.imread( ) 函数来读取图像数据&#xff0c;很少用PIL.Image…

数据结构——红黑树 and B-树

红黑树 根据平衡条件第4、5两点 最短路径&#xff0c;都是黑色 最长路径&#xff0c;红黑相间 最长是最短的两倍 B-树

Android集成OpenSSL实现加解密-集成

导入so 将编译生成的 OpenSSL 动态库文件&#xff08;.so 文件&#xff09;复制到你的 Android 项目的 libs 目录中 导入头文件 将编译生成的include文件夹导入到项目中 build.gradle添加配置 defaultConfig {……testInstrumentationRunner "androidx.test.runner…

大厂前端面试题总结(百度、字节跳动、腾讯、小米.....),附上热乎面试经验!

先简单介绍下自己&#xff0c;我“平平无奇小天才”一枚&#xff0c;毕业于南方普通985普通学生&#xff0c;有幸去百度、字节面试&#xff0c;感觉大公司就是不一样&#xff0c;印象最深的是字节&#xff0c;所以有必要总结一下面试经验&#xff0c;以及面试中遇到的一些问题&…

SuperMap iServer发布的ArcGIS REST 地图服务如何通过ArcGIS API进行要素查询

作者&#xff1a;yx 前言 前面我们介绍了SuperMap iServer发布的ArcGIS REST 地图服务如何通过ArcGIS API加载&#xff0c;这里呢我们再来看看如何进行要素查询呢&#xff1f; 一、服务发布 SuperMap iServer发布的ArcGIS REST 地图服务如何通过ArcGIS API加载已经介绍如何发…

gem5学习(7):内存系统中创建 SimObjects--Creating SimObjects in the memory system

目录 一、gem5 master and slave ports 二、Packets 三、Port interface 1、主设备发送请求时从设备忙 2、从设备发送响应时主设备忙 四、Simple memory object example 1、Declare the SimObject 2、Define the SimpleMemobj class 3、Define the SimpleMemobj class…

docker compose 部署 grafana + loki + vector 监控kafka消息

Centos7 随笔记录记录 docker compose 统一管理 granfana loki vector 监控kafka 信息。 当然如果仅仅是想通过 Grafana 监控kafka&#xff0c;推荐使用 Grafana Prometheus 通过JMX监控kafka 目录 1. 目录结构 2. 前提已安装Docker-Compose 3. docker-compose 自定义服…

009:vue结合el-table实现表格行拖拽排序(基于sortablejs)

文章目录 1. 实现效果2. 安装 sortablejs 插件3. 完整组件代码4. 注意点 1. 实现效果 2. 安装 sortablejs 插件 sortablejs 更多用法 cnpm i --save sortablejs3. 完整组件代码 <template><div class"home"><div class"body"><el-ta…

车路协同中 CUDA 鱼眼相机矫正、检测、追踪

在车路协同中,鱼眼一般用来补充杆件下方的盲区,需要实现目标检测、追踪、定位。在目标追踪任务中,通常的球机或者枪机方案,无法避免人群遮挡的问题,从而导致较高的ID Swich,造成追踪不稳定。但是鱼眼相机的顶视角安装方式,天然缓解了遮挡的问题,从而实现杆件下方的盲区…

用通俗易懂的方式讲解大模型:Prompt 提示词在开发中的使用

OpenAI 的 ChatGPT 是一种领先的人工智能模型&#xff0c;它以其出色的语言理解和生成能力&#xff0c;为我们提供了一种全新的与机器交流的方式。但不是每个问题都可以得到令人满意的答案&#xff0c;如果想得到你所要的回答就要构建好你的提示词 Prompt。本文将探讨 Prompt 提…

VSCODE : SSH远程配置+免密登录

SSH基础配置 填入地址&#xff0c;回车 ssh userhost-or-ip 然后选择默认的配置&#xff0c;回车&#xff0c;得到以下结果&#xff1a; 点击链接 选择远程的系统 输入密码 免密登录 生成SSH密钥&#xff1a; 首先&#xff0c;确保你已经在本地生成了SSH密钥。你可以使…

Hive中支持毫秒级别的时间精度

实际上&#xff0c;Hive 在较新的版本中已经支持毫秒级别的时间精度。你可以通过设置 hive.exec.default.serialization.format 和 mapred.output.value.format 属性为 1&#xff0c;启用 Hive 的时间精度为毫秒级。可以使用以下命令进行设置&#xff1a; set hive.exec.defau…

unity学习笔记----游戏练习02

一、阳光值的展示和消耗 1.创建一个文本组件用于显示阳光的数值&#xff0c;然后在脚本中得到这个UI。 在SunManger中得到这个组件的引用 public TextMeshProUGUI sunPointText; 写一个用于更新显示的方法 public void UpdataSunPointText() { sunPointText.tex…

IntelliJ IDE 插件开发 | (四)开发一个时间管理大师插件

系列文章 IntelliJ IDE 插件开发 |&#xff08;一&#xff09;快速入门IntelliJ IDE 插件开发 |&#xff08;二&#xff09;UI 界面与数据持久化IntelliJ IDE 插件开发 |&#xff08;三&#xff09;消息通知与事件监听IntelliJ IDE 插件开发 |&#xff08;四&#xff09;开发一…

MIT线性代数笔记-第31讲-线性变换及对应矩阵

目录 31.线性变换及对应矩阵打赏 31.线性变换及对应矩阵 线性变换相当于是矩阵的抽象表示&#xff0c;每个线性变换都对应着一个矩阵 例&#xff1a; 考虑一个变换 T T T&#xff0c;使得平面上的一个向量投影为平面上的另一个向量&#xff0c;即 T : R 2 → R 2 T:R^2 \to R…

【Spark精讲】一文讲透Spark RDD

MapReduce的缺陷 MR虽然在编程接口的种类和丰富程度上已经比较完善了&#xff0c;但这些系统普遍都缺乏操作分布式内存的接口抽象&#xff0c;导致很多应用在性能上非常低效 。 这些应用的共同特点是需要在多个并行操 作之间重用工作数据集 &#xff0c;典型的场景就是机器学习…

Mybatis行为配置之Ⅰ—缓存

专栏精选 引入Mybatis Mybatis的快速入门 Mybatis的增删改查扩展功能说明 mapper映射的参数和结果 Mybatis复杂类型的结果映射 Mybatis基于注解的结果映射 Mybatis枚举类型处理和类型处理器 再谈动态SQL 文章目录 专栏精选摘要引言正文缓存配置项说明cacheEnabledlocal…

SASS循环

<template><div><button class"btn type-1">默认按钮</button><button class"type-2">主要按钮</button><button class"type-3">成功按钮</button><button class"type-4">信息…

VSCode 如何安装插件的历史版本

背景 在日常开发过程中&#xff0c;我们可能会遇到新版VSCode插件存在问题&#xff0c;无法正常工作的情况。这种情况下&#xff0c;一种可行的解决方案就是安装插件的历史版本。VSCode 插件默认安装的都是插件最新的版本&#xff0c;例如下面 vscode-styled-compoents 插件 本…

C语言之进制转换

C语言之进制转换 一、引言二、十进制与二进制、八进制、十六进制三、二进制与八进制、十六进制四、八进制与十六进制 一、引言 在C语言中&#xff0c;经常使用的整数的进制有十进制、二进制、十六进制&#xff08;在C语言中以0x或0X为前缀&#xff09;、八进制&#xff08;在C…