维护经常使用的对象池并从池中抓取一个而不是创建新对象的专业人员和成员是什么?类似于字符串实习的东西,除了它可以用于所有类对象.
例如,它可以被认为是好的,因为它节省了gc时间和对象创建时间.另一方面,如果从多个线程使用它,它可能是同步瓶颈,需要显式解除分配并引入内存泄漏的可能性.通过占用可回收的内存,它会给垃圾收集器带来额外的压力.
优化的第一定律:不要这样做.第二定律:不要这样做,除非你真的已经测量并知道你需要优化的事实和地点.
只有当对象的创建成本非常高,并且它们实际上可以被重用时(你可以只用公共操作将状态重置为可以重用的东西),它就会有效.
你提到的两个收获并不是真的:java中的内存分配是免费的(成本接近10个cpu指令,这没什么).因此,减少对象的创建只会节省您在构造函数中花费的时间.对于可以重用的非常重的对象(数据库连接,线程)而言,这可能是一个好处,而不会改变:您重用相同的连接,相同的线程.
GC时间不会减少.事实上它可能会更糟.对于移动的世代GC(Java是或者高达1.5),GC运行的成本取决于活动对象的数量,而不是释放的内存.活动对象将被移动到内存中的另一个空间(这使得内存分配如此之快:每个GC块内的空闲内存是连续的)几次被标记为旧并移动到旧一代内存空间之前.
作为GC,编程语言和支持的设计考虑到了常见的用法.如果您在许多情况下避开常见用法,最终可能会更难以阅读效率较低的代码.
除非创建对象很昂贵,否则我不会打扰.
优点:
创建的对象较少 - 如果对象创建很昂贵,这可能很重要.(规范示例可能是数据库连接,其中"创建"包括与服务器建立网络连接,提供身份验证等)
缺点:
更复杂的代码
共享资源=锁定; 潜在的瓶颈
违反GC对象生命周期的期望(大多数对象将是短期的)
你有解决的实际问题,还是这种推测?除非你有基准测试/配置文件显示存在问题,否则我不会考虑做这样的事情.
池化意味着您通常不能使对象不可变.这导致了defencive复制,所以你最终会制作比你刚制作一个新的不可变对象更多的副本.
不可变性并不总是令人满意的,但通常你会发现事情是不可改变的.使它们不是不可变的,以便您可以在池中重用它们可能不是一个好主意.
所以,除非你确定这是一个问题,否则不要打扰.使代码清晰易懂,可能性足够快.如果不是,那么代码清晰且易于遵循的事实将使其更容易加速(通常).
别.
这是2001年的思考.现在一天仍然有价值的唯一对象"池"是单身.我仅使用单例来减少用于分析的对象创建(因此我可以更清楚地看到影响代码的是什么).
你还有其他任何东西只是为了没有好的目的而破坏记忆.
继续并在创建1,000,000个对象时运行配置文件.这是微不足道的.
这里的旧文章.
它完全取决于你创建对象的成本,与你创建它们的次数相比 ......例如,只是美化结构的对象(例如,只包含几个字段,除了访问器之外没有其他方法)是一个真正的汇集用例.
一个现实生活中的例子:我需要从生成大量整数/等级对的过程中重复提取n个排名最高的项(整数).我在有界优先级队列中使用了"pair"对象(一个整数和一个浮点排名值).重新使用这些对,而不是清空队列,抛弃它们并重新创建它们,产生了20%的性能提升......主要是在GC充电中,因为在JVM的整个生命周期中都不需要重新分配对.