一、单例模式是什么?
例:实例化,对象。表示只需要创建一个对象。
应用场景:比如百度,假如百度是一个类,搜索功能是一个方法,我们需要创建一个百度对象,然后调用搜索的方法做事情,如果有很多人访问,我们需要创建很多个百度对象然后调用其搜索方法,显然不合理,我们只需要一个百度对象,目的是调用搜索方法,所以我们想只创建一个百度对象,把百度对象设置为单例的。
二、如何思考?如何写?
//不让他人随意创造对象
//将构造方法私有
private Singleton(){}
//但是需要创造一个对象
//类的成员有: 属性 方法 构造方法 块
// 构造方法??如果在构造方法里面创建对象,那无法调用,构造方法需要私有
// 块???块里面无法提供返回值
//普通方法???public static Singleton xxx(){ new Singleton }
//只能保证方法是一个,但是无法保证只能执行一次,创建一个对象
// 只能放在属性里面了
// static静态属性保证对象只有一份且能通过类直接调用
// private私有保证属性不能被随意更改
private static Singleton singleton = new Singleton();
// 需要提供一个方法,获取对象
// 但是没有对象无法直接调用,static可以不用创建对象,用类调用
public static Singleton getInstance(){
return singleton;
}
三、有哪些不足?如何改进?
方法一:饿汉式(立即加载)
缺点:一上来就创建对象,如果没有用,占用内存,浪费内存空间。
private Singleton(){}
private static Singleton singleton = new Singleton();
public static Singleton getInstance(){
return singleton;
}
方法二:懒汉式(延迟加载)
优点:避免占用过多内存。
缺点:多线程不安全。
private Singleton(){}
private static Singleton singleton;
public static Singleton getInstance(){
if (singleton==null){
singleton = new Singleton();
}
return singleton;
}
方式三:加锁,保证线程安全。
缺点:在方法上加锁,导致效率较慢
private Singleton(){}
private static Singleton singleton;
public static synchronized Singleton getInstance(){
if (singleton==null){
singleton = new Singleton();
}
return singleton;
}
方法四:在方法内加锁,双重锁,提高运行效率。
缺点:可能会出现:jvm虚拟机,对象的开辟和赋值过程中,出现指令重排序。
private Singleton(){}
private static Singleton singleton;
public static Singleton getInstance(){
if (singleton==null){
synchronized (Singleton.class){
if (singleton==null){
singleton = new Singleton();
}
}
}
return singleton;
}
方法五:在属性上加volatile,能解决上述问题。
(写到这里,单例模式已经很完美了)
private Singleton(){}
private static volatile Singleton singleton;
public static Singleton getInstance(){
if (singleton==null){
synchronized (Singleton.class){
if (singleton==null){
singleton = new Singleton();
}
}
}
return singleton;
}