Java重用(静态?)对象作为临时对象以提高性能
我需要在模拟循环中经常使用多个方法调用类的方法 其中一些方法需要访问临时对象以在其中存储信息。离开该方法后,不再需要存储的数据。 例如:Java重用(静态?)对象作为临时对象以提高性能,java,android,static,allocation,temporary,Java,Android,Static,Allocation,Temporary,我需要在模拟循环中经常使用多个方法调用类的方法 其中一些方法需要访问临时对象以在其中存储信息。离开该方法后,不再需要存储的数据。 例如: Class class { method1() { ... SomeObject temp = new SomeObject(); ... } method2() { ... SomeObject temp = new SomeObject();
Class class {
method1() {
...
SomeObject temp = new SomeObject();
...
}
method2() {
...
SomeObject temp = new SomeObject();
SomeObject temp2 = new SomeObject();
...
}
}
我需要尽可能地优化。最昂贵(可移动)的问题是发生了太多的分配。
我认为最好不要每次都为这些对象分配所需的空间,所以我希望保留它们
以静态方式存储它们是否更有效?
比如:
还是有更好的办法?谢谢你的帮助
根据答案编辑:
实际的问题不是内存占用,而是垃圾收集清除了混乱。
SomeObject是一个类似Point2D的类,内存并不昂贵(在我看来)。
我不确定使用(最终是静态的)类级对象作为占位符还是使用我不知道的更高级的方法更好。请记住,
temp
和temp2
本身不是对象,而是指向类型为SomeObject
的对象的变量。按照您计划的方式,唯一的区别是temp
和temp2
将是实例变量而不是局部变量。召唤
temp = new SomeObject();
仍然会在堆上分配一个新的SomeObject
此外,将它们设置为静态或实例变量而不是本地变量将导致最后分配的SomeObject
s保持强可访问性(只要您的类
实例在实例变量的作用域内),从而防止在重新分配变量之前对其进行垃圾收集
以这种方式进行优化可能是无效的。当前,一旦temp
和temp2
超出范围,它们指向的SomeObject
s将有资格进行垃圾收集
如果您仍然对内存优化感兴趣,则需要显示
SomeObject
是什么,以便获得有关如何缓存它所保存的信息的建议。这些对象有多大。在我看来,您可以拥有类级别的对象(不一定是静态的,我会回到那个上来)。对于SomeObject,您可以有一个清除其内容的方法。在一个地方使用完后,调用该方法以清除其内容
就静态而言,多个调用方是否会使用该类并具有不同的值?如果是这样,就不要使用static。首先,您需要确保您确实存在此问题。垃圾收集器的好处是它自动处理所有临时对象 无论如何,假设您运行一个单线程应用程序,并且在任何给定时间内最多使用MAX_对象。一种解决方案可以是这样的:
public class ObjectPool {
private final int MAX_OBJECTS = 5;
private final Object [] pool = new Object [MAX_OBJECTS];
private int position = 0;
public Object getObject() {
// advance to the next object
position = (position + 1) % MAX_OBJECTS;
// check and create new object if needed
if(pool[position] == null) {
pool[position] = new Object();
}
// return next object
return pool[position];
}
// make it a singleton
private ObjectPool() {}
private static final ObjectPool instance = new ObjectPool();
public static ObjectPool getInstance() { return instance;}
}
下面是使用示例:
public class ObjectPoolTest {
public static void main(String[] args) {
for(int n = 0; n < 6; n++) {
Object o = ObjectPool.getInstance().getObject();
System.out.println(o.hashCode());
}
}
}
您可以注意到,第一个和最后一个数字是相同的-MAX_OBJECTS+1迭代返回相同的临时对象。在这个预成熟优化的示例中,我会很小心。通常情况下,它会使代码更复杂(而且复杂性会使错误更容易出现)、更难阅读、可能会引入错误、可能无法提供预期的加速等。对于表示二维点坐标的简单对象,我不担心重复使用。通常,如果您使用大量内存、避免冗长昂贵的构造函数,或者将对象构造从频繁执行的紧循环中拉出,那么重用将获得最大的好处 您可以尝试一些不同的策略: 将责任推送到调用方一种方法是让调用方传入预初始化的对象,使方法参数为final。但是,这是否有效取决于您需要对对象执行什么操作 指向临时对象作为方法参数的指针另一种方法是让调用者作为对象作为参数传递,其目的基本上是作为指向对象的指针,方法应该在其中进行临时存储。我认为这一技术在C++中更为常用,但工作原理类似,虽然有时出现在图形编程等地方。 对象池重用临时对象的一种常见方法是使用对象池,其中对象是从固定的“可用”对象库中分配的。这有一些开销,但是如果对象很大,并且经常只在短时间内使用,因此内存碎片可能是一个问题,那么开销可能会足够小,因此值得考虑 成员变量如果您不关心对该方法的并发调用(或使用同步来防止此类调用),则可以通过为存储创建类的成员变量来模拟“局部静态”变量的C++ism。它会降低代码的可读性,并使使用变量的代码的其他部分受到意外干扰的空间稍大一些,但开销比对象池低,并且不需要更改方法签名。如果执行此操作,还可以选择在变量上使用
transient
关键字,以指示该变量不需要序列化
除非该方法也是静态的,否则我会暂时避免使用静态变量,因为在程序运行的整个过程中,这可能会产生内存开销,这是不可取的,并且与成员变量的缺点相同x2(同一类的多个实例)尝试对象池如何知道分配周期正在消耗您的效率?你分析过你的代码吗?如果你使用的是安卓系统,你的设备处理器周期好,速度快,你不是为10HZ处理器编码
public class ObjectPoolTest {
public static void main(String[] args) {
for(int n = 0; n < 6; n++) {
Object o = ObjectPool.getInstance().getObject();
System.out.println(o.hashCode());
}
}
}
0) 1660364311
1) 1340465859
2) 2106235183
3) 374283533
4) 603737068
5) 1660364311