Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.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_Design Patterns_Singleton - Fatal编程技术网

Java单例模式-对实例化变量的更新

Java单例模式-对实例化变量的更新,java,design-patterns,singleton,Java,Design Patterns,Singleton,想弄明白关于单身模式的一些事情 如果我实现了如下所示的单例模式,我该怎么做才能让其他类更新并看到字段someString和somesint的更新 从我读到的关于Singleton模式的内容来看,不变性不是先决条件之一。因此,从技术上讲,我可以为字段设置setter方法并对其进行更改,使这些更改对其他类可见吗?例如,如果我有另外两个类实现Runnable并每隔几秒钟打印一次Foo的字段。我尝试了这个,结果是每个类只看到自己的更新,而其他类则没有 public class Foo { pri

想弄明白关于单身模式的一些事情

如果我实现了如下所示的单例模式,我该怎么做才能让其他类更新并看到字段someString和somesint的更新

从我读到的关于Singleton模式的内容来看,不变性不是先决条件之一。因此,从技术上讲,我可以为字段设置setter方法并对其进行更改,使这些更改对其他类可见吗?例如,如果我有另外两个类实现Runnable并每隔几秒钟打印一次Foo的字段。我尝试了这个,结果是每个类只看到自己的更新,而其他类则没有

public class Foo {
    private static Foo instance;
    private String someString;
    private int someNum;

    private Foo(){
        someString = "a";
        someNum = 1;
    }

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

    public void setSomeString(String someString) {
        this.someString = someString;
    }

    public void setSomeNum(int someNum) {
        this.someNum = someNum;
    }

    @Override
    public String toString() {
        return "Foo{" +
                "someString='" + someString + '\'' +
                ", someNum=" + someNum +
                '}';
    }
}
---更新--- 添加了2个类(下面的Baz和Bar),并使用setter更新了Foo,并重写了toString()

首先运行Baz,我希望它每秒打印foo.toString(),并使用最新的值

然后运行Bar,它首先更新Foo的字段,然后每秒打印Foo.toString()。来自Bar的更新仅对Bar可见,对Baz不可见

来自Baz的输出:

1443284013576 Foo{someString='a',somesnum=1}

1443284014576 Foo{someString='a',someNum=1}

1443284015576 Foo{someString='a',someNum=1}

1443284016577 Foo{someString='a',somesnum=1}

1443284017577 Foo{someString='a',someNum=1}

1443284018577 Foo{someString='a',somesnum=1}

条形图的输出:

1443284016416 Foo{someString='abc',someNum=2}

public class Baz {
    public static void main(String[] args) throws InterruptedException {
        Foo foo = Foo.getInstance();
        while(true){
            System.out.println(foo);
            Thread.sleep(1000);
        }
    }
}


public class Bar{
    public static void main(String[] args) throws InterruptedException {
        Foo foo = Foo.getInstance();
        foo.setSomeNum(2);
        foo.setSomeString("abc");
        while(true){
            System.out.println(foo);
            Thread.sleep(1000);
        }
    }
}
1443284017417 Foo{someString='abc',someNum=2}

public class Baz {
    public static void main(String[] args) throws InterruptedException {
        Foo foo = Foo.getInstance();
        while(true){
            System.out.println(foo);
            Thread.sleep(1000);
        }
    }
}


public class Bar{
    public static void main(String[] args) throws InterruptedException {
        Foo foo = Foo.getInstance();
        foo.setSomeNum(2);
        foo.setSomeString("abc");
        while(true){
            System.out.println(foo);
            Thread.sleep(1000);
        }
    }
}
1443284018417 Foo{someString='abc',someNum=2}

public class Baz {
    public static void main(String[] args) throws InterruptedException {
        Foo foo = Foo.getInstance();
        while(true){
            System.out.println(foo);
            Thread.sleep(1000);
        }
    }
}


public class Bar{
    public static void main(String[] args) throws InterruptedException {
        Foo foo = Foo.getInstance();
        foo.setSomeNum(2);
        foo.setSomeString("abc");
        while(true){
            System.out.println(foo);
            Thread.sleep(1000);
        }
    }
}
1443284019418 Foo{someString='abc',somesnum=2}

public class Baz {
    public static void main(String[] args) throws InterruptedException {
        Foo foo = Foo.getInstance();
        while(true){
            System.out.println(foo);
            Thread.sleep(1000);
        }
    }
}


public class Bar{
    public static void main(String[] args) throws InterruptedException {
        Foo foo = Foo.getInstance();
        foo.setSomeNum(2);
        foo.setSomeString("abc");
        while(true){
            System.out.println(foo);
            Thread.sleep(1000);
        }
    }
}
1443284020418 Foo{someString='abc',somesnum=2}

public class Baz {
    public static void main(String[] args) throws InterruptedException {
        Foo foo = Foo.getInstance();
        while(true){
            System.out.println(foo);
            Thread.sleep(1000);
        }
    }
}


public class Bar{
    public static void main(String[] args) throws InterruptedException {
        Foo foo = Foo.getInstance();
        foo.setSomeNum(2);
        foo.setSomeString("abc");
        while(true){
            System.out.println(foo);
            Thread.sleep(1000);
        }
    }
}

更新:一些愚蠢的打字错误是的,你可以使用setter和getter。。要从另一个类访问setter,可以使用Foo.getInstance().setSomeString(someString)

从singleton类中,如果创建了对象,则由于singleton模式,不允许任何对象修改someNum和someString值。在多线程应用程序中,可能有机会打破单例模式。这将导致您的值不可靠。

Java要求程序员在多线程程序中明确包含一些访问共享资源的机制。Java为此提供了许多特性,但是初学者可能应该从类中所有相关方法的synchronized关键字开始。在您的示例中,如果不同步getInstance()方法,可能会生成多个类实例。如果未能同步其他方法,则可能会出现不确定性行为

要获得同步访问的好处,只需在方法声明中添加
synchronized
关键字,例如。
public static synchronized Foo getInstance(){
public synchronized void setSomeString(String someString){

您有两个独立的主方法,因此您可能在单独的JVM中运行每个类。相反,创建一个主方法,在不同的线程中运行每个类,然后运行该主方法

您还需要将
Foo
中的方法声明为synchronized或等效的方法,以确保在所有线程中都可以看到更新

public class Foo {
    private static Foo instance;
    private String someString;
    private int someNum;

    private Foo() {
        someString = "a";
        someNum = 1;
    }

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

    public synchronized void setSomeString(String someString) {
        this.someString = someString;
    }

    public synchronized void setSomeNum(int someNum) {
        this.someNum = someNum;
    }

    @Override
    public synchronized String toString() {
        return "Foo{" +
                "someString='" + someString + '\'' +
                ", someNum=" + someNum +
                '}';
    }
}

public class Baz implements Runnable {
    public void run() {
        Foo foo = Foo.getInstance();
        while(true) {
            System.out.println("Baz: " + foo);
            try {
                Thread.sleep(1000);
            } catch(InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


public class Bar implements Runnable {
    public void run() {
        Foo foo = Foo.getInstance();
        foo.setSomeNum(2);
        foo.setSomeString("abc");
        while(true) {
            System.out.println("Foo: " + foo);
            try {
                Thread.sleep(1000);
            } catch(InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        new Thread(new Bar()).start();
        new Thread(new Baz()).start();
    }
}

仅仅是一个FYI,对于线程安全,您应该考虑使用<代码> GETStaseNo.()/Case>一个同步方法。您可以用您所尝试的设置器来发布示例吗?当您声明<代码> GETSimule方法时,会发生什么情况??@BYTERIDER请参见above@JamesKPolk如果我的问题与同步有关,我不希望看到更新或获得ConcurrentModificationException吗?请参阅我的更新。问题仍然存在于上述类中。请参阅我的更新。我不希望不可变。只是将单个变量的更新发布到其他类的一种方法。请参阅