编辑:我正在尝试为Web应用程序的所有会话创建共享数据库连接池。另一篇文章说,创建servlet上下文对象的最佳方法是让init监听器创建它。然而,我不知道如何使这个对象可供我的servlet使用。
答案 0 :(得分:2)
一种解决方案是使用私人持有者类:
public class SomeClass {
private static class ResourceHolder {
private static final Resource INSTANCE = new Resource();
}
public static Resource getInstance() {
return ResourceHolder.INSTANCE;
}
}
第一次调用SomeClass.getInstance()
时,将初始化实例。
答案 1 :(得分:2)
另一种方法是使用静态初始化:
public class SomeClass {
private static final Object[] CONTENT;
static {
CONTENT = new Object[SomeOtherClass.getContentSize()]; // To show you can access runtime variables
}
}
一旦使用ClassLoader加载类,这将初始化CONTENT
数组。
答案 2 :(得分:1)
最简单的延迟初始化是使用enum
和一个实例。
enum Singleton {
INSTANCE; // lazy initialised
}
增加的问题是你想要初始化值。要处理这个问题,您可以嵌套该类。
enum Utility {;
static MyType val;
static OtherType val2;
enum Holder {
INSTANCE;
Holder() {
// uses val and val2
}
}
public static Holder getInstance(MyType val, OtherType val2) {
Utility.val = val;
Utility.val2 = val2;
return Holder.INSTANCE; // only created the first time.
}
}
注意:这是线程安全的,因为静态块初始化是安全的。
答案 3 :(得分:0)
类似的东西:
public static abstract class Lazy<T> {
private T t = null;
public synchronized T get() {
if (t == null) {
t = create();
}
return t;
}
protected abstract T create();
}
public static final Lazy<List<String>> lazyList = new Lazy<List<String>>(){
@Override
protected List<String> create() {
return new ArrayList<String>();
}
};
答案 4 :(得分:0)
我会提前告诫你,你所描述的有一点代码味道,我怀疑你会做得更好,完全避免这种模式。依赖于外部运行时状态的静态资源会破坏有关变量范围的各种最佳实践。
然而,您所描述的内容最好由Supplier
或Future
实现,具体取决于成功构建所需对象所涉及的工作。差异有点迂腐,但你通常使用Future
来保存一个需要很长时间才能计算的引用,而Supplier
通常会很快返回。 Future
也有一些与Java的并发实用程序有很好的挂钩,但听起来它并不需要它。
你会像Supplier
这样使用:
public class GlobalState {
public static final Supplier<LazyData> MY_DATA = Suppliers.memoize(
new Supplier<LazyData>() {
public LazyData get() {
// do whatever you need to construct your object, only gets executed once needed
}
});
...
}
Suppliers.memoize()
将以线程安全的方式将第一次调用的结果缓存到基础Supplier
,因此简单地包装您使用此调用定义的Supplier
可以防止重复处理。