想要了解一下单身人士模式。
如果我实现如下所示的单例模式,我可以做什么,以便其他类可以更新并查看someString和someInt字段的更新?
从我读到的关于Singleton模式的内容来看,不变性不是先决条件之一。从技术上讲,我可以为字段设置setter方法并更改它们,并将这些更改显示给其他类吗?例如,如果我有另外两个类实现Runnable并且每隔几秒打印一次Foo字段。我试过这个,发生了什么事情,每个班级只看到自己的更新而没有其他班级。#/ p>
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 添加了2个类(下面的Baz和Bar)并使用setter更新了Foo并覆盖了toString()。
首先运行Baz我希望它每秒都以最新的值打印foo.toString()。
然后运行Bar,它首先更新Foo的字段,然后每秒打印foo.toString()。 Bar的更新仅对Bar可见,而不是Baz。
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}
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);
}
}
}
更新:一些愚蠢的错别字
答案 0 :(得分:1)
Java要求程序员明确地包含一些机制,以便synchronizing访问多线程程序中的共享资源。 Java为此提供了许多功能,但初学者应该从类的所有相关方法的synchronized关键字开始。在您的示例中,如果不同步getInstance()方法,则可能会生成多个类的实例。如果未能同步您的其他方法,您将面临非确定性行为的风险。
要获得同步访问的好处,您只需将synchronized
关键字添加到方法声明中,例如:
public static synchronized Foo getInstance(){
和public synchronized void setSomeString(String someString) {
答案 1 :(得分:1)
您有两个独立的主要方法,因此您可能在单独的JVM中运行每个类。而是创建一个main方法,在不同的线程中运行每个类,然后运行它。
您还需要将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();
}
}
答案 2 :(得分:0)
是的,您可以使用setter和getter。要从另一个类访问setter,请使用Foo.getInstance()。setSomeString(someString)。
答案 3 :(得分:-1)
从您的单件类,如果创建了对象,则不允许任何对象修改someNum&由于单例模式,someString值。在多线程应用程序中可能有机会破坏单例模式。这将导致您的价值不可靠。