单例模式:因程序需要,有时我们只需要某个类同时保留一个对象,不希望有更多对象,此时,我们则应考虑单例模式的设计。
这里需要实例化但不使用new方式,可以在构造方法前面添加private,私有化构造方法。
(使用背景:所有类都有构造方法,不单独编写构造方法则系统默认使用空构造,单独编写构造方法的话,默认的构造器就会失效)
然后需要单独创建一个公共方法来专门返回一个类实例。在该方法中需要对是否实例化有一个判断,若没有实例化过,有调用private的构造方法new一个实例,然后该实例可以被继续调用当有需要的时候,同一个类中private方法可以被访问。
单例模式
保证一个类有只能有一个实例,并提供访问他的全局访问点。
单例模式结构图:
好处:
保证唯一实例
严格控制其他类的访问,不会出现资源冲突,其他类每次只能访问一个该类。可控性强。
懒汉式
第一次调用就实例化自己,
第一次就是在之前没有该对象,需要的时候才创建自己。
(使用时才被激活)
一般写法:
public class Singleton{
private Singleton(){}
private static Singleton single = null;
public static Singleton getInstance(){
if(sigle == null){
sigle = new Singleton();
}
}
}
在多线程模式下,可能会被多次实例化。
书上说该方法不安全线程不安全
改进:
1.在gentInstance方法上加上同步锁
public static synchronized Singleton getInstance(){
if(single == null){
single = new Singleton();
}
return single;
}
2.可以使用双重检查
public static Singleton getInstance(){
if(single == null){
synchronized(Singleton.class){
if(single == null){
single = new Singleton();
}
}
}
return single;
}
3.静态内部类
public class Singleton{
private static class LazyHolder{
private static final Singleton Intance= new Singleton();
}
}
*推荐使用,实现了线程安全,避免了同步锁造成的性能影响。
饿汉式
在类初始化的时候,已经存在一个唯一对象,本身是线程安全的
public class singleton{
private Singleton(){}
private static final Singleton single = new Singleton();
public static Single gentInstance(){
return single;
}
}
对象一开始就创建好了,不会出现多线程中的被多次创建的问题。
这是我在看书之前自己的总结:
所谓懒汉和饿汉模式设计思路一样,区别在创建实例化对象的时机.
懒汉式:在程序中一开始就有一个实例化对象,只是在需要调用的时候直接调用该对象,公共方法就只是返回该对象。
饿汉式:他就是上面的描述过程,在共有的方法中判断是否已经存在该对象,然后选择是否创建该对象。
还是有所收获的。
懒汉式与饿汉式区别
线程安全
饿汉式天生就是线程安全的,可以直接用于多线程;
懒汉式本身是非线程安全的,为了实现线程安全有上面的1、2、3三种方式,这三种方式在资源和性能上有写区别
资源加载和性能
饿汉式在类创建的同时就实例化一个静态对象,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为资源已经初始化完成。
而懒汉式顾名思义,会延迟加载,在第一次使用该单例的会后才会实例化对象出来第一次调用时要做初始化,如果要做的工作比较多,性能上会有延迟,之后就和饿汉式一样
针对懒汉式1、2、3三种实现的区别
1:在方法上调用了同步锁,虽让线程安全了,但是每次都要同步,会影响性能.
2:在getInstance中做了两次判断对象存在性的检查,确保了只有第一次调用单例的时候才会去同步,这样既实现了线程安全,同时避免了每次都同步的性能损耗
3:利用classLoader机制(类加载机制)来保证初始化instance时既能只有一个线程,所以也是线程安全的,同时没有性能损耗,推荐这种
话说:静态初始化就是饿汉式呀
参考链接
链接:https://www.jianshu.com/p/11c8748dcce7
來源:简书