Java 中线程安全单例工厂
这是我一直用于返回线程安全单例的工厂的基本模式的示例:
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;
}
}
它使用易失性和双重检查惯用法来确保创建单个实例并且在线程之间可见。
在 1.6+ 中是否有更简洁和/或更便宜的方法来实现相同的目标。
This is a sample of the basic pattern I've been using for a Factory that returns a thread-safe 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;
}
}
It uses both volatile and the double check idiom to ensure that a single instance is created and is visible across threads.
Is there a less verbose and/or less expensive way to accomplish the same goal in 1.6+.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
使用 Initialization On Demand Holder 习惯用法,它更简单,可读性更好:
但是,我更喜欢 < a href="http://butunclebob.com/ArticleS.UncleBob.SingletonVsJustCreateOne" rel="noreferrer">只创建一个成语。
更新:正如您的问题历史记录所证实的那样,您正在使用 Java EE。如果您的容器支持它,您也可以将其设为
@Singleton
EJB 并使用@EJB
来注入它(尽管@Stateless
更可取,因为@Singleton
默认情况下是读锁定的)。例如在 JSF 托管 bean 中,
这样您就可以将实例化作业委托给容器。
Use the Initialization On Demand Holder idiom, it's simpler and better readable:
However, I'd prefer Just Create One idiom.
Update: as your question history confirms, you're using Java EE. If your container supports it, you could also make it a
@Singleton
EJB and use@EJB
to inject it (although@Stateless
is preferable since@Singleton
is by default read-locked).with e.g. in a JSF managed bean
This way you delegate the instantiation job to the container.
您可以让类加载器执行其 maigc 并在启动时初始化静态变量 - 这保证可以工作,因为类加载器保证单线程行为。
如果您想延迟初始化实例并且大部分是无锁的,那么不行,您必须这样做,并确保您使用的是 Java >= 1.5
编辑:请参阅 BalusC 的解决方案,它更智能地使用类加载器。请注意,这一切之所以有效,是因为类加载器延迟初始化类 - 即它们仅在第一次访问时加载 - 并且因为内部类在这方面的处理方式与普通类一样(仅仅因为加载外部类并不意味着内部类)类已加载)
You could let the class loader do its maigc and initialize the static variable at startup - this is guaranteed to work, because the classloader guarantees single threaded behavior.
If you want to initialize the instance lazily and mostly lockfree, then no, you have to do it this way and make sure you're using Java >= 1.5
Edit: See BalusC's solution that uses the classloader a bit more intelligently. Note that this all works because the classloader initializes classes lazily - ie they're only loaded at their first access - and because inner classes are handled just like normal classes in that regard (just because you load the outer class doesn't mean the inner class is loaded)
为什么不只是
Why not just