Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/383.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java中线程安全单例的工厂_Java_Multithreading_Singleton_Factory - Fatal编程技术网

Java中线程安全单例的工厂

Java中线程安全单例的工厂,java,multithreading,singleton,factory,Java,Multithreading,Singleton,Factory,这是我为返回线程安全单例的工厂使用的基本模式的一个示例: public class UserServiceFactory { private volatile static UserService userService; private UserServiceFactory() { } public static UserService getInstance() { if (userService == null) { s

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

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+中,是否有一种不太冗长和/或成本较低的方法来实现相同的目标。

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

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

编辑:请参阅BalusC的解决方案,它更智能地使用类加载器。请注意,这一切都是有效的,因为类加载器会延迟初始化类(即它们只在第一次访问时加载),而且内部类在这方面的处理方式与普通类一样(加载外部类并不意味着加载内部类)

为什么不

public synchronized static UserService getInstance() {
    if (userService == null) {
        userService = new UserServiceImpl();    
    }
    return userService;
}
使用这个成语,它更简单,可读性更好:

public class UserServiceFactory {

    private UserServiceFactory () {}

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

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

}
然而,我更喜欢成语


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

例如,在JSF管理的bean中

@EJB
private UserService userService;

通过这种方式,您可以将实例化作业委托给容器。

因为您总是会得到锁开销,尽管您只在第一次调用函数时需要它。不,它不是从Java 1.5开始的。请仔细阅读对volatile所做的更改,这些更改使它工作起来。@Voo:我意识到了这一点,于是我删除了这个短语。是的,volatile的更改早就该完成了。使多线程编程至少简单一点。无论如何,对于内部类的智能使用+1——让VM在幕后完成复杂的工作总是一个好主意;)这个例子看起来很像我想象中的优化。实例被声明为static final,所以如果UserService需要很长时间由thread1构建,那么thread2会等待吗?@BalusC——我喜欢它,这正是我想要的。非常感谢你。我也喜欢读“JustCreateOne”这个成语。这里肯定有一些值得思考的东西。可能是重复的。恕我直言,我要求这个问题不要重复上述内容。我提供了一个特定的代码示例,并根据最近和近期对Java内存模型的更改要求可能的增强。如果基于更一般的前一个问题而不允许这种类型的提问,那么我们将失去一些对最终用户的价值——否?另请参见和
@EJB
private UserService userService;