这是我一直用于Factory的基本模式的示例,它返回一个线程安全的Singleton:
public class UserServiceFactory {
private volatile static UserService userService;
private UserServiceFactory() { }
public static UserService getInstance() {
if (userService == null) {
synchronized(UserServiceImpl.class) {
if (userService == null) {
userService = new UserServiceImpl();
}
}
}
return userService;
}
}
它使用volatile和double check惯用法来确保创建单个实例并在线程中可见。
在1.6 +中实现相同目标是否有更简洁和/或更便宜的方式。
答案 0 :(得分:19)
使用Initialization On Demand Holder成语,它更简单,更易读:
public class UserServiceFactory {
private UserServiceFactory () {}
private static class UserServiceHolder {
private static final UserService INSTANCE = new UserService();
}
public static UserService getInstance() {
return UserServiceHolder.INSTANCE;
}
}
但是,我更喜欢Just Create One成语。
更新:正如您的问题历史记录所确认的那样,您正在使用Java EE。如果您的容器支持它,您也可以使它成为@Singleton
EJB并使用@EJB
来注入它(尽管@Stateless
更可取,因为@Singleton
默认是读取锁定的) 。
@Singleton
public class UserService {}
例如在JSF托管bean中
@EJB
private UserService userService;
这样您就可以将实例化作业委派给容器。
答案 1 :(得分:3)
您可以让类加载器执行其maigc并在启动时初始化静态变量 - 这可以保证正常工作,因为类加载器可以保证单线程行为。
如果你想懒惰地初始化实例并且大多数是无锁的,那么不,你必须这样做,并确保你使用Java> = 1.5
编辑:请参阅BalusC的解决方案,该解决方案更智能地使用类加载器。请注意,这一切都有效,因为类加载器懒惰地初始化类 - 即它们仅在第一次访问时加载 - 并且因为内部类在这方面就像普通类一样处理(仅仅因为加载外部类并不意味着内部类)加载了类)
答案 2 :(得分:0)
为什么不
public synchronized static UserService getInstance() {
if (userService == null) {
userService = new UserServiceImpl();
}
return userService;
}