Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.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 - Fatal编程技术网

Java单例类和多线程

Java单例类和多线程,java,multithreading,singleton,Java,Multithreading,Singleton,乡亲们- 我有一个helper类,它的任务是基于参数构建一些消息。该类本身没有任何私有数据(当然实例除外) 我知道单例类不是多线程友好的。在本例中,当两个线程试图同时执行buildSetRequest()时会发生什么情况 谢谢你抽出时间 编辑: 根据我的需要,正如@BoristheSpide在下面的评论中所建议的那样,我将把这个类作为一个实用类,并进行以下更改: 1.最后决定。 2.使方法成为静态的。 3.删除所有单例引用 public final class RequestBuilder {

乡亲们- 我有一个helper类,它的任务是基于参数构建一些消息。该类本身没有任何私有数据(当然实例除外)

我知道单例类不是多线程友好的。在本例中,当两个线程试图同时执行buildSetRequest()时会发生什么情况

谢谢你抽出时间

编辑: 根据我的需要,正如@BoristheSpide在下面的评论中所建议的那样,我将把这个类作为一个实用类,并进行以下更改: 1.最后决定。 2.使方法成为静态的。 3.删除所有单例引用

public final class RequestBuilder {

    private RequestBuilder() {}

    public static SetRequest buildSetRequest(Path prefix,
                                      Path path,
                                      ConfigEntity configEntity,
                                      Any protoAnyData) {
        .....
        .....
        return setRequest;
    }

    public static GetRequest buildGetRequest(Path prefix,
                                      Path Path,
                                      RetrieveRequestEntity retrieveRequestEntity,
                                      Encoding encoding) {
        .....
        .....
        return getRequest;
    }
}

我将保留原始代码,因为它仍然有效,并为注释和回答这个问题提供了上下文。

在本例中,不要太多,因为您的构造函数是空的(其他人提到的没有共享状态)。当您有多个必须初始化的私有实例变量时,就会出现问题。在这种情况下,您需要一些保护,如doble检查:

private static volatile RequestBuilder instance;

private RequestBuilder() {}

public static RequestBuilder getInstance() {
    if (instance == null) {
        synchronized (RequestBuilder.class) {
            if (instance == null) {
                instance = new RequestBuilder();
            }
        }
    }
    return instance;
}
原因是线程可以随时挂起。如果构建实例的当前线程被挂起,而另一个线程出现,则可能存在半初始化的实例变量,并且对象可能最终处于损坏状态

编辑:关于
buildSetRequest()


代码在一个方法中,如果这个方法自己创建实例或使用线程安全类,就不会有任何问题。

在这种情况下,不会有太多问题,因为你的构造函数是空的(其他人说没有共享状态)。当您有多个必须初始化的私有实例变量时,就会出现问题。在这种情况下,您需要一些保护,如doble检查:

private static volatile RequestBuilder instance;

private RequestBuilder() {}

public static RequestBuilder getInstance() {
    if (instance == null) {
        synchronized (RequestBuilder.class) {
            if (instance == null) {
                instance = new RequestBuilder();
            }
        }
    }
    return instance;
}
原因是线程可以随时挂起。如果构建实例的当前线程被挂起,而另一个线程出现,则可能存在半初始化的实例变量,并且对象可能最终处于损坏状态

编辑:关于
buildSetRequest()



代码在一个方法中,如果该方法本身创建自己的实例或与线程安全类一起工作,则不会有任何问题。

这只是惰性初始化和急切初始化之间的区别。请阅读有关类初始值设定项的规则-从构造的角度来看,OP的代码是完全安全的。@Boristespider感谢投反对票。是的,但是OP将一个单例类的事实与对
buildSetRequest()
的调用混为一谈,我不知道如何集中回答。谢谢你的反馈,请随意扩展我的解释。对不起,这不是你回答的重点。这是关于你答案的整个第一部分是错误的。根据Java语言规范,一个半初始化的实例不可能泄漏。你的建议给关于并发的虚假“事实”增加了虚假的复杂性。@BoristSpider不管怎样,但我的回答是正确的。选中此项,您将看到Java内存模型有效地允许发布部分初始化的对象:。同样,你也可以回答OP的问题。这是一个完全不同的例子。您的意思是类初始化器不受JVM保护。构造函数调用受类初始化器保护。我不知道还有什么好说的——这个答案从根本上是不正确的,并且传播了关于Java如何工作的危险的错误信息。作为一名专业人士,我要求您删除它。这只是懒惰或急切初始化之间的区别。请阅读有关类初始值设定项的规则-从构造的角度来看,OP的代码是完全安全的。@Boristespider感谢投反对票。是的,但是OP将一个单例类的事实与对
buildSetRequest()
的调用混为一谈,我不知道如何集中回答。谢谢你的反馈,请随意扩展我的解释。对不起,这不是你回答的重点。这是关于你答案的整个第一部分是错误的。根据Java语言规范,一个半初始化的实例不可能泄漏。你的建议给关于并发的虚假“事实”增加了虚假的复杂性。@BoristSpider不管怎样,但我的回答是正确的。选中此项,您将看到Java内存模型有效地允许发布部分初始化的对象:。同样,你也可以回答OP的问题。这是一个完全不同的例子。您的意思是类初始化器不受JVM保护。构造函数调用受类初始化器保护。我不知道还有什么好说的——这个答案从根本上是不正确的,并且传播了关于Java如何工作的危险的错误信息。作为一名专业人士,我要求您删除它。如果没有共享状态,即没有字段,则可以。。。。尽管这确实引出了一个问题,那就是为什么你需要一个单身汉。只要把它变成一个实用类,就可以了。那么
buildSetRequest
到底是什么呢?如果该调用修改了
configEntity
参数;两个调用线程使用相同的
ConfigEntity
实例。。那么你可能会有问题(因为你共享了可变状态)@Daniele,不,没有一个输入被修改。如果没有共享状态,也就是说没有字段,那就好了。。。。尽管这确实引出了一个问题,那就是为什么你需要一个单身汉。只要把它变成一个实用类,就可以了。那么
buildSetRequest
到底是什么呢?如果该调用修改了
configEntity
参数;两个调用线程使用相同的
ConfigEntity
实例。。那么你可能会有问题(因为你共享了可变状态)@Daniele,不,没有一个输入被修改。