我在单身设计模式中工作。我使用一个静态变量作为我的类的成员变量。根据我的代码它创建了多个实例,即使我是单独的类。请帮帮我,这是正确的做事方式吗? //这是我的代码
public class MySingleton {
public static MySingleton instance = null;// new MySingleton();
static int count;
private MySingleton() {
count++;
}
public static MySingleton getInstance() {
if (instance == null) {
synchronized (MySingleton.class) {
instance = new MySingleton();
}
}
return instance;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
MySingleton news = new MySingleton().getInstance();
System.out.println(news.count);
MySingleton news1 = new MySingleton().getInstance();
System.out.println(news1.count);
MySingleton news2 = new MySingleton().getInstance();
System.out.println(news2.count);
}
}
答案 0 :(得分:2)
您的代码不是线程安全的。
假设您从2个主题到MySimgleton().getInstance()
如果在if之后发生上下文切换,那么你将创建2个实例
答案 1 :(得分:1)
您需要使用静态方法来访问类,以允许类控制对其唯一实例的访问
MySimgleton news = new MySimgleton().getInstance();
应该是
MySimgleton news = MySimgleton.getInstance();
但这种懒惰的初始化方法不是线程安全的。你可以做到
public class MySingleton {
private static class SingletonHolder {
static final MySingleton INSTANCE = new MySingleton();
}
public static MySingleton getInstance() {
return SingletonHolder.INSTANCE;
}
...
}
答案 2 :(得分:1)
在Main函数中,它应该是:
public static void main(String[] args) {
// TODO Auto-generated method stub
MySimgleton news = MySimgleton.getInstance();
System.out.println(news.count);
MySimgleton news1 = MySimgleton.getInstance();
System.out.println(news1.count);
MySimgleton news2 = MySimgleton.getInstance();
System.out.println(news2.count);
}
对于这种情况,它更好:
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
MySimgleton news = MySimgleton.getInstance();
System.out.println(news.count);
MySimgleton news1 = MySimgleton.getInstance();
System.out.println(news1.count);
MySimgleton news2 = MySimgleton.getInstance();
System.out.println(news2.count);
}
}
class MySimgleton {
public static MySimgleton instance = null;// new MySimgleton();
static int count;
private MySimgleton() {
count++;
}
public static MySimgleton getInstance() {
if (instance == null) {
synchronized (MySimgleton.class) {
instance = new MySimgleton();
}
}
return instance;
}
}
答案 3 :(得分:0)
要避免多线程访问错误,请在声明中初始化instance
。
如果您确实想要在getInstance
方法中对其进行初始化,请将同步块包裹在if
语句周围,并使字段instance
private
(远程final
}关键字)
通过类名访问getInstance方法,不要先调用构造函数。
public class MySimgleton {
// You don't need a synchronized block if you initialize it in the declaration
public static final MySimgleton instance = new MySimgleton();
static int count;
private MySimgleton() {
count++;
}
public static MySimgleton getInstance() {
// Only if you didn't initialize it in the declaration itself.
// synchronized (MySimgleton.class) {
// if (instance == null) {
// instance = new MySimgleton();
// }
// }
return instance;
}
public static void main(String[] args) {
MySimgleton news = MySimgleton.getInstance();
System.out.println(news.count);
// etc.
}
}
答案 4 :(得分:0)
您的代码的问题在于您自己调用构造函数
new MySimgleton().
即使构造函数是私有的,您也可以从类中调用它。
您应该调用静态getInstance方法来获取对象的实例,并且可以直接通过Class接收静态mehtod。
MySimgleton.getInstance();
答案 5 :(得分:0)
您的类首先是单线程应用程序的完美单例,
唯一的事情是你有一个名为count的静态varibale,static对你创建的所有对象都是通用的,而evrytime你创建的对象是你递增计数因此它给出1,2,3输出。
但是尝试打印对象,您将看到相同的引用地址
我将打印状态添加到打印对象并获得如下
2
com.kb.designpatterns.MySingleton@15db9742
3
com.kb.designpatterns.MySingleton@15db9742
com.kb.designpatterns.MySingleton@15db9742
4
答案 6 :(得分:0)
正如@Mzf提到的那样
您的代码不是线程安全的
您可以通过在同步块中包含if (instance == null)
来解决问题。
但是,为了在极度多线程的环境中最小化同步影响,您可以考虑进行双重检查:
public static MySingleton getInstance() {
if (instance == null) {
synchronized (MySingleton.class) {
if (instance == null) {
instance = new MySingleton();
}
}
}
return instance;
}