单例模式,顾名思意就是就是单独唯一的对象实例。通过java本身的访问修饰符(static)其实很容易就控制实例唯一。但是有的时候设计的更规范的略复杂的模式会让你更加贴合实际的需求。
看一个经典又简单(但不一定正确)的例子:
public class Singleon {
private static Singleton uniqueInstance;
public Singleton() {}
public static Singleton getInstance() {
if(uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
这就是很经典又简单的例子,但是为什么说不一定正确呢,是因为在多线程的情况下访问这段代码是很有可能会产生不唯一的对象实例,没图纯解释一波,在线程先后访问其中的if代码段,然后此时代码也都没执行到实例化对象,也就是这时其他的线程访问这个代码段时也是进入了if中,这就会导致会实例化不止一个对象,这就违反了单例模式的设计思想。
解决办法有以下俩种:
- synchronized关键字,基于锁的同步方式来控制线程安全问题,缺点就是同步方法的执行效率非常低。
public class Singleton {
private static Singleton uniqueInstance;
private Singleton() {}
//加上synchronized关键字
public static synchronized Singleton getInstance() {
if(uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
}
- 使用线程安全的static关键字,相对上一个方式更加直接了当,jvm加载类的时候就实例化静态变量。
public class Singleton {
private static Singleton uniqueInstance = new Singleton();
private Singleton() {}
//加上synchronized关键字
public static Singleton getInstance() {
return uniqueInstance;
}
}