Java 中线程安全单例工厂

发布于 2024-11-09 04:07:08 字数 601 浏览 0 评论 0原文

这是我一直用于返回线程安全单例的工厂的基本模式的示例:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一萌ing 2024-11-16 04:07:08

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

}

但是,我更喜欢 < a href="http://butunclebob.com/ArticleS.UncleBob.SingletonVsJustCreateOne" rel="noreferrer">只创建一个成语。


更新:正如您的问题历史记录所证实的那样,您正在使用 Java EE。如果您的容器支持它,您也可以将其设为 @Singleton EJB 并使用 @EJB 来注入它(尽管 @Stateless 更可取,因为 @Singleton 默认情况下是读锁定的)。

@Singleton
public class UserService {}

例如在 JSF 托管 bean 中,

@EJB
private UserService userService;

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

Use the Initialization On Demand Holder idiom, it's simpler and better readable:

public class UserServiceFactory {

    private UserServiceFactory () {}

    private static class UserServiceHolder {
        private static final UserService INSTANCE = new UserService();
    }

    public static UserService getInstance() {
        return UserServiceHolder.INSTANCE;
    }

}

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).

@Singleton
public class UserService {}

with e.g. in a JSF managed bean

@EJB
private UserService userService;

This way you delegate the instantiation job to the container.

我只土不豪 2024-11-16 04:07:08

您可以让类加载器执行其 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)

梦年海沫深 2024-11-16 04:07:08

为什么不只是

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

Why not just

public synchronized static UserService getInstance() {
    if (userService == null) {
        userService = new UserServiceImpl();    
    }
    return userService;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文