单例模式
保证类在内存中只有一个对象
1)控制类的创建,不让其他类创建本类的对象,即设置private属性
2)在本类中定义一个本类的对象
public class test {
public static void main(String[] args) {
//分别实例化对象 s1,s2
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
System.out.println(s1 == s2);
}
}
class Singleton{
//私有的构造函数,保证外类不能实例化本类
private Singleton(){
}
//自己创建一个类的实例化
private static Singleton singleton = new Singleton();
//创建一个get方法,返回一个实例s
public static Singleton getInstance(){
return singleton;
}
}
1.饿汉模式
直接创建出类的实例化;
简单来说就是空间换时间,因为直接就实例化一个对象,占用了内存,
class Singleton {
private static Singleton instance = new Singleton();
private Singleton() {
}
public static Singleton getInstance() {
return instance;
}
}
2.懒汉模式
在需要的时候再创建类的实例化
简单的来说就是时间换空间,与饿汉式正好相反
(1)单线程
class Singleton {
private static Singleton instance ;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
(2) 懒汉模式-多线程版-性能低
加上监视器锁,保证线程安全.
class Singleton {
private static Singleton instance = null;
private Singleton() {}
public synchronized static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
效率低的原因:
多个线程同时启动,调用getInstance() 方法,第一个进入该方法的线程,会以线程安全的方式创建对象,并返回,
此时, 对象已经实例化,而其他线程依旧以同步互斥的方式获取对象,而这个步骤是可以并发执行的,现在是按顺序进行的,所以性能低.
(3.)懒汉模式-多线程版-二次判断-性能高
双重检验锁.
//防止代码重排序,需要给变量加上volatile关键字;
class Singleton {
//防止代码重排序,需要加上volatile关键字;
private static volatile Singleton instance = null;
private Singleton() {
}
public static Singleton getInstance() {
if (instance == null) {//第一个if
synchronized (Singleton.class) {
if (instance == null) {//第二个if
//两个线程A和B同时访问静态方法并同时运行到第一个if判断语句,
//这时线程A先进入同步代码块中实例化对象,结束之后线程B也进入同步代码块,
//如果没有第二个if判断语句,那么线程B也同样会执行实例化对象的操作了。
instance = new Singleton();
}
}
}
return instance;
}
}