繁体   English   中英

Java中线程安全单例的工厂

[英]Factory for Thread Safe Singleton in Java

这是我一直用于工厂的基本模式的示例,它返回一个线程安全的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+中的相同目标。

使用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;

这样,您可以将实例化作业委派给容器。

您可以让类加载器执行其maigc并在启动时初始化静态变量 - 这保证可以工作,因为类加载器可以保证单线程行为。

如果你想懒惰地初始化实例并且大多数是无锁的,那么不,你必须这样做,并确保你使用Java> = 1.5

编辑:请参阅BalusC的解决方案,该解决方案更智能地使用类加载器。 请注意,这一切都有效,因为类加载器懒惰地初始化类 - 即它们仅在第一次访问时加载 - 并且因为内部类在这方面就像普通类一样处理(仅仅因为加载外部类并不意味着内部类)加载了类)

为什么不呢

public synchronized static UserService getInstance() {
    if (userService == null) {
        userService = new UserServiceImpl();    
    }
    return userService;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM