Java Singleton类中的非静态成员

Java Singleton类中的非静态成员,java,multithreading,methods,static,singleton,Java,Multithreading,Methods,Static,Singleton,我正在做一个单身的课程,如下所示 public class SingletonTest { private static SingletonTest instance; private Integer result; private SingletonTest() { } public synchronized static SingletonTest getInstance(){ if(instance == null){

我正在做一个单身的课程,如下所示

public class SingletonTest {

    private static SingletonTest instance;

    private Integer result;

    private SingletonTest() {   
    }

    public synchronized static SingletonTest getInstance(){
        if(instance == null){
            instance = new SingletonTest();
        }
        return instance;
    }

    public Integer calculateResult(int value1, int value2) {
        result = value1 + value2;
        return result;
    }
}
但是,当我使用JMeter从多个线程调用非静态成员时,就会出现问题

举例来说:

线程1: SingletonTest.getInstance.calculateResult1,2->返回3

线程2: SingletonTest.getInstance.calculateResult3,2->返回3


我认为发生这种情况是因为两个线程同时访问一个名为result的方法和重写de属性。

没错,第二个线程正在访问第一个线程设置的结果值

如果要修改对多个线程可见的值,则应同步该操作

public synchronized Integer calculateResult(int value1, int value2) {
    result = value1 + value2;
    return result;
}
这样,调用该方法的第一个线程将获得单例上的锁,而第二个线程在其完成之前无法访问它


如果要使用并发性,您可能需要查看。如果您是对的,第二个线程正在访问第一个线程的结果集的值

如果要修改对多个线程可见的值,则应同步该操作

public synchronized Integer calculateResult(int value1, int value2) {
    result = value1 + value2;
    return result;
}
这样,调用该方法的第一个线程将获得单例上的锁,而第二个线程在其完成之前无法访问它

如果要使用并发性,您可能应该查看。尤其是。

试试这个

public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
         return instance;
    }
}
试试这个

public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {
         return instance;
    }
}

您的猜测是正确的,这是因为您的共享结果实例变量不是线程安全的。 不知道你为什么要分享它。修复代码如下:

public class SingletonTest {

    private static SingletonTest instance;

    private SingletonTest() {   
    }

    public synchronized static SingletonTest getInstance(){
        if(instance == null){
            instance = new SingletonTest();
        }
        return instance;
    }

    public Integer calculateResult(int value1, int value2) {
        Integer result = value1 + value2;
        return result;
    }
}

您的猜测是正确的,这是因为您的共享结果实例变量不是线程安全的。 不知道你为什么要分享它。修复代码如下:

public class SingletonTest {

    private static SingletonTest instance;

    private SingletonTest() {   
    }

    public synchronized static SingletonTest getInstance(){
        if(instance == null){
            instance = new SingletonTest();
        }
        return instance;
    }

    public Integer calculateResult(int value1, int value2) {
        Integer result = value1 + value2;
        return result;
    }
}


是的,你有比赛条件。这与它是一个单态无关,而与不安全地改变共享状态有关。您需要同步,或者使用类似AtomicInteger的东西。这里真正的问题是什么?是的,这就是单身汉的工作方式。您有一个共享状态的实例。这是很有可能的-您必须应用锁机制来防止竞争条件。甚至不需要实例变量。calculateResult方法可以返回局部变量。那么就不需要同步了。@fge-初始化是线程安全的,因为getInstance是同步的。是的,您有一个竞争条件。这与它是一个单态无关,而与不安全地改变共享状态有关。您需要同步,或者使用类似AtomicInteger的东西。这里真正的问题是什么?是的,这就是单身汉的工作方式。您有一个共享状态的实例。这是很有可能的-您必须应用锁机制来防止竞争条件。甚至不需要实例变量。calculateResult方法可以返回局部变量。那么就不需要同步了。@fge-初始化是线程安全的,因为getInstance是同步的。你需要在C中用google实现singleton,你的答案无论如何都不能解决OPs问题。你需要在C中用google实现singleton,你的答案无论如何也不能解决OPs问题。我已经阅读了,这种同步非常昂贵,性能方面的同步方法的运行速度比不同步的方法慢100倍。如何提高性能?@Hector尝试使用实例变量,返回类型只是简化问题的一个示例。在我的项目中返回的对象实际上是一个HashMap。@Hector感谢Roberto,我不知道那个类。我已经读过,同步是非常昂贵的。性能方面,同步方法的运行速度比不同步方法慢100倍。如何提高性能?@Hector尝试使用实例变量,返回类型只是简化问题的一个示例。我的项目中返回的对象实际上是一个HashMap。@Hector感谢Roberto,我不知道那个类。实例变量和返回类型只是一个简化问题的示例。在我的项目中返回的对象实际上是一个HashMap。好吧,这很公平,但如果您在问题中加入真实的数据结构,这将很有帮助,因为对于基于操作的不同数据结构,使它们线程安全可能是不同的。如果使用ConcurrentHashMap及其CAS操作putifabsent,则可以得到预期的结果,而不是使用HashMap。我可以修改我的代码,如果你让我知道你正在使用什么作为关键。希望有帮助。实例变量和返回类型只是简化问题的一个示例。在我的项目中返回的对象实际上是一个HashMap。好吧,这很公平,但如果您在问题中加入真实的数据结构,这将很有帮助,因为对于基于操作的不同数据结构,使它们线程安全可能是不同的。如果使用ConcurrentHashMap及其CAS操作putifabsent,则可以得到预期的结果,而不是使用HashMap。我可以修改我的代码,如果你让我知道你正在使用什么作为关键。希望 这很有帮助。