当前位置:首页 >综合 >对象池模式: 一种有效减小开销、提高性能的模式 也可以使用他的抽象类

对象池模式: 一种有效减小开销、提高性能的模式 也可以使用他的抽象类

2024-06-30 20:12:00 [百科] 来源:避面尹邢网

对象池模式: 一种有效减小开销、对象的模提高性能的池模模式

作者:JAVA旭阳 开发 前端 对象池模式是一种强大的设计模式,可以通过重用昂贵的式种式对象显著提高应用程序性能和效率。它提供了一种管理共享资源的有效机制,并通过限制创建的开销对象数量来防止资源耗尽。如果使用得当,提高对象池模式可以成为提高软件应用程序的对象的模可伸缩性和可靠性的有效工具。

​前言

对象池模式是池模软件开发中广泛使用的设计模式,旨在通过重用创建成本高昂的式种式对象来提高应用程序性能和效率。它在创建对象的有效新实例非常耗时且对象创建频率很高的情况下特别有用。当可以创建的开销对象实例数量由于资源限制而受到限制时,此模式也很有用。提高

工作机制

图片

对象池模式: 一种有效减小开销、提高性能的模式 也可以使用他的抽象类

对象池模式的对象的模工作原理是创建一个预初始化对象池,可以根据需要借用和归还这些对象。池模不是式种式每次需要时都创建一个新对象,而是在池中搜索可以重用的可用对象。如果对象可用,则将其从池中移除并返回给请求对象,否则,将创建一个新对象并将其添加到池中。

对象池模式: 一种有效减小开销、提高性能的模式 也可以使用他的抽象类

代码实现对象池

我这边通过使用Apache Common Pool来实现对象的池化技术。

对象池模式: 一种有效减小开销、提高性能的模式 也可以使用他的抽象类

  1. 引入依赖
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.9.0</version>
</dependency>
  1. 需要池化的对象示例
public class Foo { 

private final String username;

public Foo(String username) {
this.username = username;
}

public String getUsername() {
return username;
}
}
  1. 构建对象创建工厂 可以直接实现org.apache.commons.pool2.PooledObjectFactory<T>接口实现创建、销毁、钝化、取消等接口,也可以使用他的抽象类,实现创建和包装方法即可。
public class FooPoolObjectFactory extends BasePooledObjectFactory<Foo> { 

@Override
public Foo create() throws Exception {
return new Foo(String.valueOf(RandomUtils.randomInt(0, 10)));
}

@Override
public PooledObject<Foo> wrap(Foo obj) {
return new DefaultPooledObject<>(obj);
}
}
  1. 实现驱逐策略。我们有必要定期对对象的"健康状态"进行检查,剔除掉"不能用"的对象,并填充新的对象给"对象池"。一般数据库链接对象,要定期进行心跳,确保连接可用,如果连接断开,需要销毁对象,并重新创建新的对象。common-pool中,我们可以实现驱逐策略,对对象进行定期检查。
public class FooEvictionPolicy implements EvictionPolicy<Foo> { 

@Override
public boolean evict(EvictionConfig config, PooledObject<Foo> underTest, int idleCount) {
// todo 定期检查对象某些功能是否可用
return true;
}
}
  1. 构建&配置对象池
public GenericObjectPool<Foo> fooGenericObjectPool() { 
GenericObjectPoolConfig<Foo> poolConfig = new GenericObjectPoolConfig<>();
poolConfig.setEvictionPolicy(new FooEvictionPolicy());
poolConfig.setBlockWhenExhausted(true);
poolConfig.setJmxEnabled(false);
poolConfig.setMaxWaitMillis(1000 * 10);
poolConfig.setTimeBetweenEvictionRunsMillis(60 * 1000);
poolConfig.setMinEvictableIdleTimeMillis(20 * 1000);
poolConfig.setTestWhileIdle(true);
poolConfig.setTestOnReturn(true);
poolConfig.setTestOnBorrow(true);
poolConfig.setMaxTotal(3);
// 设置抛弃策略
AbandonedConfig abandonedConfig = new AbandonedConfig();
abandonedConfig.setRemoveAbandonedOnMaintenance(true);
abandonedConfig.setRemoveAbandonedOnBorrow(true);
return new GenericObjectPool<>(new FooPoolObjectFactory(), poolConfig, abandonedConfig);
}
  1. 获取&归还对象
private final GenericObjectPool<Foo> fooGenericObjectPool = fooGenericObjectPool();

public Foo borrowFoo () throws Exception {
return fooGenericObjectPool.borrowObject();
}

public void returnObject(Foo foo){
fooGenericObjectPool.returnObject(foo);
}

对象池优点

  • 提高性能,对象池模式可以通过减少与对象创建和销毁相关的开销来显着提高应用程序的性能。通过重用预先初始化的对象,该模式减少了需要创建的对象数量,进而减少了创建新对象所需的时间和资源。
  • 资源管理,对象池模式提供了一种管理共享资源的机制,例如数据库连接或文件句柄。通过限制创建的对象数量,该模式可以防止资源耗尽并确保资源得到有效共享。
  • 一致性,对象池模式可以通过确保所有对象在使用前都预先初始化为已知状态来帮助确保应用程序的一致性。这在对象初始化复杂或耗时的情况下特别有用。
  • 易于实现,对象池模式相对容易实现,可用于多种情况。它是一种经过验证的设计模式,已在许多应用程序和编程语言中成功使用。

对象池缺点

  • 增加复杂性,对象池模式可以通过添加额外的抽象层来增加应用程序的复杂性。这会使代码更难理解和维护,尤其是在池大小和对象生命周期管理不当的情况下。
  • 开销,虽然对象池模式可以通过减少与对象创建和销毁相关的开销来提高性能,但由于池本身的管理,它也会引入额外的开销。如果池大小没有针对应用程序的需要进行优化,这种开销会变得很大。
  • 有限的灵活性:对象池模式旨在管理一组固定的对象,可能不适合需要动态对象创建或可变池大小的应用程序。
  • 线程安全,如果多个线程同时访问池,对象池模式会引入线程安全问题。同步机制必须到位以确保一次只有一个线程可以访问池,这可能会增加额外的开销和代码的复杂性。
  • 资源泄漏,如果对象没有正确返回到池中,它们可能会“泄漏”并且无法重用。随着时间的推移,这会导致资源耗尽并降低应用程序性能。

应用场景

一般需要池化的对象往往都是比"重量级"较的对象,创建和销毁都比较耗时,比如我们的线程,数据库连接对象,TCP连接对象,FTP连接对象 等等,我们来具体看几个例子把。

  1. Web服务器例子

Web 服务器通常需要处理大量并发请求,这会给系统资源带来巨大压力。通过使用对象池来管理数据库连接、网络套接字或其他资源,从而提高Web 服务器的性能和可扩展性,避免资源耗尽。

  • 连接池类
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class ConnectionPool {
private static final int MAX_POOL_SIZE = 10;
private static final int MAX_WAIT_TIME = 5000; // milliseconds
private static final int PORT_NUMBER = 8080;

private final BlockingQueue<Socket> pool;
private final ServerSocket serverSocket;

public ConnectionPool() throws Exception {
pool = new ArrayBlockingQueue<>(MAX_POOL_SIZE);
serverSocket = new ServerSocket(PORT_NUMBER);
System.out.println("Server started on port " + PORT_NUMBER);
}

public Socket getConnection() throws Exception {
Socket connection = pool.poll();

if (connection == null) {
try {
connection = serverSocket.accept();
System.out.println("New connection accepted from " + connection.getInetAddress());
} catch (SocketTimeoutException e) {
System.out.println("Timeout waiting for connection. No connection found within " + MAX_WAIT_TIME + " milliseconds.");
}
}

return connection;
}

public void returnConnection(Socket connection) {
if (pool.size() < MAX_POOL_SIZE) {
pool.offer(connection);
System.out.println("Connection returned to pool. Pool size is now " + pool.size());
} else {
try {
connection.close();
System.out.println("Connection pool is full. Discarded connection.");
} catch (Exception e) {
System.out.println("Error closing discarded connection.");
}
}
}

public static void main(String[] args) throws Exception {
ConnectionPool connectionPool = new ConnectionPool();

while (true) {
Socket connection = connectionPool.getConnection();
// Do some work with the connection
Thread.sleep(5000);
connectionPool.returnConnection(connection);
}
}
}

在此示例中, ConnectionPool类用于管理到 Web 服务器的网络连接池,构造函数将连接池初始化为最大 10 个连接,并在端口号 8080 上启动服务器。

调用getConnection()方法可以从池中返回一个连接对象,如果池为空,则从服务器套接字接受新连接。它最多等待 5 秒以使连接可用,然后超时并返回 null。

如果池未满,则 returnConnection ()方法将连接对象添加回池中,如果池已满,则关闭连接并丢弃它。

在 main ()​ 方法中,创建ConnectionPool对象,并在循环中重复获取连接并返回到池中。这是对象池模式如何用于管理 Web 服务器中的连接以有效利用资源的示例。

  1. 游戏开发种的例子

游戏通常需要快速创建和销毁大量对象,例如粒子、子弹或敌人。通过使用对象池来管理这些对象,游戏可以提高性能并减少与对象创建和销毁相关的开销。

  • GameObjectPool 类
import java.util.ArrayList;
import java.util.List;

public class GameObjectPool {

class GameObject {
public void reset() {
// reset object to default state
}
}

private static final int MAX_POOL_SIZE = 10;

private final List<GameObject> pool;

public GameObjectPool() {
pool = new ArrayList<>(MAX_POOL_SIZE);
for (int i = 0; i < MAX_POOL_SIZE; i++) {
pool.add(new GameObject());
}
}

public GameObject getObject() {
GameObject gameObject = pool.remove(0);
gameObject.reset();
return gameObject;
}

public void returnObject(GameObject gameObject) {
if (pool.size() < MAX_POOL_SIZE) {
pool.add(gameObject);
}
}

public static void main(String[] args) {
GameObjectPool gameObjectPool = new GameObjectPool();

// Use game objects from pool
GameObject gameObject1 = gameObjectPool.getObject();
// modify gameObject1
gameObjectPool.returnObject(gameObject1);

GameObject gameObject2 = gameObjectPool.getObject();
// modify gameObject2
gameObjectPool.returnObject(gameObject2);
}
}

在此示例中,GameObjectPool​类用于管理游戏开发场景中的GameObject​对象池。构造函数将池初始化为最大大小 10,并创建GameObject对象来填充池。

调用getObject ()​方法从池中移除一个对象,并在返回之前将其重置为默认状态。如果池未满,则 returnObject ()方法将一个对象添加回池中。

在 main ()​方法中,创建 GameObjectPool对象并重复获取游戏对象并返回到池中。这是对象池模式如何用于管理游戏开发场景中的游戏对象以有效利用资源的示例。

总结

总之,对象池模式是一种强大的设计模式,可以通过重用昂贵的对象显著提高应用程序性能和效率。它提供了一种管理共享资源的机制,并通过限制创建的对象数量来防止资源耗尽。如果使用得当,对象池模式可以成为提高软件应用程序的可伸缩性和可靠性的有效工具。

责任编辑:武晓燕 来源: JAVA旭阳 对象池模式设计模式

(责任编辑:百科)

    推荐文章
    • 北交所11月13日开市通关测试 上市公司将达81家

      北交所11月13日开市通关测试 上市公司将达81家自官宣设立北京证券交易所(以下简称“北交所”)后,各项筹备工作紧锣密鼓,相关工作亦衔枚疾进。11月11日,北交所在官网发布通知表示,将于11月13日开展开市通关测试。伴随北交所 ...[详细]
    • 秋糖正式开展,机构逢低布局食品饮料了?

      秋糖正式开展,机构逢低布局食品饮料了?一年一度的秋季糖酒会在深圳正式开展了,作为食品行业最大的秋季盛会,数以千计的品牌商都会到现场交流行业信息,每年都能有最新鲜的的行业动态以及新机遇被发掘。因此历年来,糖酒会都被视为食品饮料行业的催化剂。 ...[详细]
    • 技术栈

      技术栈技术栈 | Ceph构件及组件分析作者:侯玉彬 2018-12-28 10:21:03存储 存储软件 Ceph 存储集群由几个不同的daemon组成,每个daemon负责Ceph 的一个独特功能并。每 ...[详细]
    • 宝馨科技(002514):2023年10月12日因换手率达20%而异动上榜

      宝馨科技(002514):2023年10月12日因换手率达20%而异动上榜宝馨科技(002514):2023年10月12日交易异动上榜,异动类型为换手率达20%,异动上榜前五卖出金额合计为166.162646百万元,异动上榜前五买入金额合计为168.605000百万元。以上 ...[详细]
    • 安逸花还完钱了每个月还扣98 具体原因是怎样的?

      安逸花还完钱了每个月还扣98 具体原因是怎样的?安逸花是由马上消费金融推出的纯信用贷款,额度高,期限长,有不少人都在上面借过钱。其中有些人借钱后碰到一种奇怪的现象,明明把安逸花的欠款还上了竟然还在扣钱,比如有人安逸花还完钱了每个月还扣98,那么这是 ...[详细]
    • 粉丝对守望2与暗黑4联动皮肤不满 认为暴雪吃相难看

      粉丝对守望2与暗黑4联动皮肤不满 认为暴雪吃相难看《守望先锋2》新赛季已正式上线,与《暗黑4》的联动皮肤也已上线。但粉丝们对联动皮肤不满,因为其不是标准高级战斗通行证的一部分,而是包含在终极战斗通行证捆绑包中,需花费40美元购买。许多人对联动皮肤的获 ...[详细]
    • 常用数据库 SQL 命令详解(上)

      常用数据库 SQL 命令详解(上)常用数据库 SQL 命令详解上)作者:鸭血粉丝Tang 2022-03-25 09:04:01数据库 MySQL 本文主要围绕 Mysql 中常用的语法进行一次梳理和介绍,这些语法大部分也同样适用于其 ...[详细]
    • 高考战役结束之时 莘莘学子如何选机

      高考战役结束之时 莘莘学子如何选机在被学校压抑了许久过后,购买的手机可谓是各位学子们真正意义上属于自己的第一部手机,因此选购时肯定要煞费苦心变形金刚Moto Z2 Play高考成绩出炉过后,对于各位准大学生来说,基本就意味着高考这个战 ...[详细]
    • 北交所开市首日三大看点 10股盘中均二次临停

      北交所开市首日三大看点 10股盘中均二次临停11月15日,中国多层次资本市场建设又将迎来里程碑事件——筹备了两个多月的北交所正式开市。从当日市场表现来看,新股表现可谓惊艳。据Wind数据统计,10只新股当日平均涨幅近20 ...[详细]
    • 微信视频号在哪里打开

      微信视频号在哪里打开我们在使用的微信软件的时候,在其中有很多的功能可以使用,在使用的时候就有小伙伴比较好奇了微信视频号在哪里打开呢?下面来来看一下微信视频号打开的方法吧。1.首先打开微信进入到首页之后点击右下角的【我的】 ...[详细]
    热点阅读