【问题标题】:Is there any reason for an object pool to not be treated as a singleton?对象池是否有任何理由不被视为单例?
【发布时间】:2011-02-09 19:24:23
【问题描述】:

我的意思不一定是使用单例模式实现,而是只拥有和使用一个池实例。我不喜欢只有一个池(或每个池类型一个)的想法。但是,我真的无法提出任何具体情况,多个池对于可变类型具有优势,至少在单个池可以发挥同样作用的任何情况下都没有。

与单例池相比,拥有多个池有什么优势?

【问题讨论】:

  • 我想知道我使用对象池(简单、可重用对象的内存/生命周期管理)的方式是否影响了我对这些答案的理解。应用程序池、线程池、连接池与我对对象池的理解对我来说是苹果与橘子的对比。

标签: design-patterns architecture singleton object-pooling


【解决方案1】:

是的,拥有多个对象池肯定有潜在的原因 - 特别是,您可能希望让一个池符合垃圾收集条件(或手动释放它等),同时保留其他池。

例如,考虑一个字符串对象池。这在 XML 的上下文中可能非常方便 - 如果您要解析相同模式的多个 XML 文档,您很可能希望汇集用于元素和属性名称的字符串。但是,一旦您完成了处理这些名称的部分,可能永远不会再使用这些名称 - 因此,当您移动到不同的文档集时,您可能希望使用不同的池。您最终可能会同时执行两项任务,在这种情况下,让两个池同时可用会很有用。

或者考虑线程池 - 我认为它是 .NET 线程池实现的一个缺点,即基本上只有一个系统线程池。我喜欢能够在服务器中拥有多个线程池的想法 - 一些线程用于低优先级批处理作业,一些用于“正常”请求,以及一些高优先级线程用于运行状况监控等作业。

【讨论】:

  • 不过,我正在考虑为可变的、短暂的对象建立一个池。 (我想我应该在问题中提到这一点。)我可以看到诸如字符串之类的多个池是如何有用的,但无法真正考虑如何将其应用于管理游戏引擎中的实体之类的需求。线程池就是一个很好的例子!
  • @Chris:当然,游戏引擎通常只运行一个游戏。然而,想象一下编写一个游戏服务器,它正在协调多个游戏。这些游戏中的每一个都可能需要自己的池......
  • 我自己对游戏服务器的经验是,您永远不会有一个可以协调每个进程多个游戏的服务器。这可能与 MMOG 有所不同,但我从来没有做过其中的一个,当然也从来没有为一个托管过服务器。
  • @Chris:这显然取决于游戏的类型,但我想有很多游戏与客户端的交互相对较少,并且您不希望每个游戏都有一个进程游戏。
【解决方案2】:

拥有什么优势 单个池上的多个池?

我认为我们使用的大多数对象池,例如 ThreadPool,为了简单起见都是作为单例实现的:这样,这些池的设计者也没有看到多实例池的用途。

但是,在少数几个地方我们确实有多个池:IIS 应用程序池和数据库连接池。

应用程序池

在 IIS 中,您可以配置多个应用程序池,以便相关的 Web 应用程序都在自己的池中运行。这种设计有几个优点,这些优点可以推广到 IIS 之外的池实现:

  • 多个对象池允许某种程度的隔离,因此一个池中的错误不应影响其他池中的对象。

  • 每个池都可以在不同的用户下运行,从而根据您的应用程序池为您提供不同级别的安全性。

  • 每个池可以有不同的错误处理程序。

  • 每个池都可以使用不同版本的 .NET 框架运行。

  • 每个池都可以有自己的 HTTP 超时。

连接池

在 SQL Server 中,对数据库的多次调用使用连接池来避免在每个查询上创建新数据库连接的开销,但是 SQL Server creates a new pool per connection string。我想这个设计背后的基本原理如下:

  • 每个池都有一个到特定数据库实例的连接。如果只有一个池包含所有连接,则需要搜索所有连接,直到找到与您请求的连接字符串匹配的连接。由于每个连接字符串有多个池,因此更容易从该特定池中提取第一个可用连接,而无需搜索其他连接。

  • 换句话说,我怀疑 SQL Server 使用多个连接池作为优化来快速获取数据库连接。

  • 我还可以想象,所有这些连接可能共享一些特定于其连接池的资源,这对于单个池来说可能是不可能的。例如,您可以指定每个连接字符串的最大连接池大小;您可能无法使用单池设计控制与特定数据库的同时连接数。

如何设计游泳池

如果不了解您的设计真正需要什么,您将无法真正选择是拥有多个池还是一个池。

如果你有一个非常简单的对象池,你也许可以摆脱单例设计。如果您确实需要额外的灵活性、定制化,或者您有一个真正独特的设置,例如分布在多个进程或机器上的对象池,那么您肯定会受益于 n-gleton 设计。

【讨论】:

  • 对于我使用对象池的方式,应用程序和连接池感觉就像是苹果和橘子。我当然可以看到他们不是单身人士的好处,但我很难将它们与我自己的游泳池使用情况进行比较。这可能是我的失败,但我忍不住从内存/生命周期管理的角度来处理池——我只是用它们来减少不断创建和销毁对象的次数。
【解决方案3】:

如果您仔细实现单例模式,您可以稍后改变主意。只需将您的类的单例封装在工厂方法后面即可。如果一切都使用它,那么您可以在以后有充分理由时允许它拥有多个实例。

public class MyClass
{
    public static MyClass GetInstance()
    {
          return singleton_ ?? (singleton = new MyClass());
    }
}

【讨论】:

  • 这不能回答问题。这不是关于如何,而是关于为什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-05
  • 2016-12-28
相关资源
最近更新 更多