Java对象重用

Java对象是否应该重复使用,因为它可以重复使用? 或者我们应该只在它们“重量级”时重用它,即具有与之相关的OS资源?

互联网上的所有旧文章尽可能地谈论对象重用和对象池,但是我已经阅读了最近的文章,说new Object()现在已经高度优化(10条指令),对象重用并不像它使用的那样大。成为。

目前的最佳做法是什么?你们这样做的人是怎样的?

我让垃圾收集器为我做了那种决定,唯一一次我用新分配的对象达到堆限制是在运行一个错误的递归算法几秒后生成3 * 27 * 27 …新对象尽可能快。

做什么是最好的可读性和封装。 有时重用对象可能很有用,但通常你不必担心它。

如果你非常密集地使用它们并且构造成本很高,你应该尽可能多地重复使用它们。

如果你的对象非常小,并且创建起来很便宜(比如Object),你应该创建新对象。

例如,连接数据库是合并的,因为创建新数据库的成本高于创建.. mmhh new Integer的成本。

所以你的问题的答案是,当它们很重并且经常使用时重用(不值得汇集仅使用两次的3 mb对象)

编辑:

此外,Effective Java: Favor Immutability中的这个项目值得一读,可能适用于您的情况。

让垃圾收集器完成它的工作,它可以被认为比你的代码更好。

除非剖析器certificate它有罪。 并且甚至不使用常识来试图找出它何时出错。 在特殊情况下,甚至像字节数组这样的廉价对象也会更好地汇集。

  • 优化规则1:不要这样做。
  • 规则2(仅限专家):不要这样做。

对象创建很便宜,是的,但有时不够便宜。

如果你快速连续地创建了很多(我的意思是A LOT)临时对象,那么垃圾收集器的成本是相当可观的。 然而,即使有一个好的分析器,你可能不一定容易看到成本,因为垃圾收集器现在在短时间内工作,而不是阻止整个应用程序一两秒。

我在项目中获得的大多数性能改进来自于通过积极的缓存来避免对象创建或避免整个工作(包括对象创建)。 无论对象有多大或多小,它仍然需要时间来创建它并管理它的引用和堆结构。 (当然,清理和内部堆碎片整理/复制也需要时间。)

我不会开始虔诚地避免不惜一切代价创建对象,但是如果你在内存分析器中看到一个拼图模式,那就意味着你的垃圾收集器处于重负荷状态。 如果您的垃圾收集器使用CPU,则CPI不适用于您的应用程序。

关于对象池:正确执行并且没有遇到内存泄漏或无效状态,或者在管理上花费的时间比保存时要困难。 所以我从未使用过这种策略。

我的策略是简单地争取不可变对象。 不可变的东西可以很容易地缓存,因此有助于保持系统简单。

但是,无论您做什么:确保首先使用分析器检查您的热点。 过早优化是最邪恶的根源。

经验法则应该是使用您的常识并在其创建消耗大量资源 (如I / O,网络流量,数据库连接等)时重用对象…

如果它只是创建一个新的String() ,忘记重用,你将从中获得任何东西。 代码可读性具有更高的偏好。

如果出现性能问题,我会担心。 首先做一些有意义的事情(你会用灵长来做这件事),如果你然后运行一个分析工具并发现它是新的导致你出现问题,那就开始考虑预分配(即当你的程序没有做太多工作时) )。

重复使用对象听起来像是等待发生的灾难:

 SomeClass someObject = new SomeClass(); someObject.doSomething(); someObject.changeState(); someObject.changeOtherState(); someObject.sendSignal(); // stuff //re-use someObject.reset(); // urgh, had to put this in to support reuse someObject.doSomethingElse(); // oh oh, this is wrong after calling changeOtherState, regardless of reset someObject.changeState(); // crap, now this is wrong but it's not obvious yet someObject.doImportantStuff(); // what's going on? 

对象创建肯定比以前更快。 JDK 5及更高版本中的新一代GC也在改进。

我认为这些都不会使对象的过度创建成本低廉,但它们确实降低了对象池的重要性。 我认为池对数据库连接有意义,但我不会尝试将它用于我自己的域对象。

重用可以提高线程安全性。 您需要仔细考虑以确保可以安全地重用对象。

如果我认为对象重用很重要,我会用Terracotta,Tangersol,GridGain等产品来做,并确保我的服务器有大量可用的内存。

第二条以上评论。

不要试着再次猜测GC和Hotspot。 对象池可能只有一次有用,但是这些日子除非你在谈论数据库连接或独特的系统资源,否则它不是那么有用。

只是尝试编写干净简单的代码,并对Hotspot可以做的事情感到惊讶。

为什么不使用VisualVM或分析器来查看代码?