更简洁的延迟加载方式

时间:2013-12-06 16:14:01

标签: java lazy-loading

我正在重构一个名为ConfigNode的类,它存储了50个“属性”。每个属性都是它自己的对象。所有属性都是可选的,大部分时间都没有设置。

目前,编写类是为了在实例化时,所有50个属性也被实例化。当您创建一百万个Config对象时,Java告诉我我正在使用2.5 GB的内存。当我注释掉属性实例化时,Java说我使用的是300 MB。

我正在使用的基准代码是

Runtime.getRuntime().gc();
// do my stuff
Runtime.getRuntime().gc();
long memory = Runtime.getRuntime().totalMemory();
System.out.println("Memory used: " + memory / 1000000 + " MB");

所以我正在考虑在访问时将类重写为延迟加载属性,但是必须编写类似

的内容
// This is probably not thread safe, so it could be even more verbose
public NodeProperty propOne() {
   if (propOne == null) {
      propOne = new NodeProperty( ... )
   }
   return propOne
}

然后对所有属性这样做似乎有点冗长。 Java中有什么可以帮助我减少必须编写的代码量(并因此维护)吗?

以下是NodeConfig的外观

public class NodeConfig {

    public NodeProperty pVersion = new NodeProperty( "Spec Version", Status.REQUIRED, Visibility.HIDDEN);
    public NodeProperty pTwoWay = new NodeProperty( "Two way", Status.OPTIONAL, Visibility.VISIBLE );
    public NodeProperty pBinary = new NodeProperty( "Binary mode", Status.OPTIONAL, Visibility.HIDDEN);

    // more properties

    public NodeConfig() {
        // 
    }
}

2 个答案:

答案 0 :(得分:2)

Guava的Suppliers库可以为你做所有延迟加载的逻辑(包括线程安全,你的例子没有)。

import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;

private Supplier<NodeProperty> propOneSupplier =
    Suppliers.memoize(() -> new NodeProperty(...));

public NodeProperty propOne()
{
    return propOneSupplier.get();
}

(请注意,这是一个番石榴供应商,而不是java.util.function.Supplier

如果您还没有使用Java 8,那么这将更加冗长:

private Supplier<NodeProperty> propOneSupplier = 
        Suppliers.memoize(
    new Supplier<NodeProperty>()
    {
        @Override
        public NodeProperty get()
        {
            return new NodeProperty(...);
        }
    });

答案 1 :(得分:0)

方法1
在给定NodeConfig代码的情况下,您可以使用另一种方法:     公共类NodeConfig {

    public NodeProperty pTwoWay;
    public NodeProperty pBinary;

    // more properties

    public NodeConfig() {
        // 
    }

    public NodeProperty getProperty(NodePropertyEnum nodeProp) {
        switch(nodeProp) {
            case TWO_WAY: 
                if (pTwoWay != null) {return pTwoWay;}
                pTwoWay = new NodeProperty( "Two way", Status.OPTIONAL, Visibility.VISIBLE ); 
            case BINARY_MODE: 
                if (pBinary != null) {return pBinary;}
                pBinary = new NodeProperty( "Binary mode", Status.OPTIONAL, Visibility.VISIBLE); 
            // other cases
            default: 
                throw new IllegalArgumentException();
        }
    }
}

方法2
看起来像Singleton设计模式的情况。不是将propOne实例检查为null,而是将所有Property类设为单例更好。类似的东西:

public class NodeProperty {

    private static volatile NodeProperty instance = null;

    private NodeProperty() {
        // instantiatin logic
    }

    public NodeProperty getInstance() {
        if(instance == null) {
            synchronized(NodeProperty.class) {
                if(instance==null) {
                    instance = new NodeProperty();
                }
            } 
        }
    }

}