简体   繁体   中英

Java singleton pattern - updates to instantiated variable

Looking to figure something out about the singleton pattern.

If I implement a singleton pattern like the below, what could I do so that other classes could update and see updates to fields someString and someInt?

From what I read about the Singleton pattern, immutability was not one of the prerequisites. So technically could I have setter methods for the fields and change them and have these changes visible to other classes? For example if I have another two classes implementing Runnable and printing Foo's fields every few seconds. I tried this and what happened was that each class sees its own updates only and none of the other classes'.

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 +
                '}';
    }
}

---UPDATE--- Added 2 classes (Baz and Bar below) and updated Foo with setters and overriden toString().

Running Baz first I expect it to print foo.toString() every second with the most up to date values.

Then running Bar, it first updates Foo's fields then prints foo.toString() every second. The updates from Bar are only visible to Bar and not to Baz.

Output from Baz:

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

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

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

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

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

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

Output from Bar:

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

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

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

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

1443284020418 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);
        }
    }
}

updated: some stupid typos

Java requires the programmer to explicitly include some mechanism for synchronizing access to shared resources in a multi-threaded program. Java provides many features for this, but the beginner should probably start with the synchronized keyword on all the relevant methods of the class. In your example, by not synchronizing the getInstance() method you risk generating more than one instance of your class. By failing to synchronized your other methods you risk non-deterministic behavior.

To get the benefits of synchronized access you simply add the synchronized keyword to your methods declaration, eg public static synchronized Foo getInstance(){ and public synchronized void setSomeString(String someString) {

You have two separate main methods so you're probably running each class in a separate JVM. Instead create a main method that runs each class in a different thread, and run that.

You also need to declare the methods in Foo as synchronized or something equivalent to guarantee that the updates are seen across all threads.

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();
    }
}

是的,您可以使用setter和getters。要从另一个类访问setter,请使用Foo.getInstance()。setSomeString(someString)。

From your singleton class , if the object is created then no objects are allowed to modify the someNum & someString values because of a singleton pattern. There may be chance to chance to break singleton pattern in multithreaded application. That will result your values as not reliable.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM