大家好,博主是个东北人哈尔滨那嘎达的,在实习中吧,感觉自己学习之路贼拉长,学习又没乐趣,感觉工作中的人都感觉我都东北话好玩儿,
那我就用东北话来分享一些知识和学习成果,这样既进步又有趣,以下有什么不对的欢迎大家呲哒我。
在我们写代码的时候总会遇到抛异常啥的,但是那玩意究竟咋用,往哪嘎达用,我就简简单单分享一下子。
单例设计模式的7种写法
咱们在面试中面试官总会问我们会什么设计模式,一般我们会说几种常见的常用的设计模式:工厂方法模式、单例模式、建造者模式、原型模式
代理........一大堆
其实说的多不如会的精几个,下面我说一下我对单例的了解,也欢迎大家指正
首先我们知道单例分为懒汉和饿汉,
第一种(懒汉,线程不安全)不建议用:
public class Singleton{ private static Singleton instance; private Singleton(){} public static Singleton getInstance(){ if (instance == null) { instance = new Singleton(); } return instance; } }
懒汉,一看我们就能知道字面意思很懒,人家调用getInstance才实例化,但是如果多线程就不安全了,当多个线程同时调用getInstance时候,可能两条线程同时判断是null
那么就可能出两个或者两个以上的实例,就违背了单例的原则,那么我们怎么能让懒汉也安全呢?
第二种(懒汉,线程安全)同步方法不建议用:
public class Singleton{ private static Singleton instance; private Singleton(){} public static synchronized Singleton getInstance(){ if (instance == null) { instance = new Singleton(); } return instance; } }
我们可以看出我们加了synchronized同步方法来控制线程安全,当一条线程执行getInstance()其他线程被阻塞,所以保证一个时刻只有一个线程访问,
但是带来致命缺点就是会效率太低了。
第三种(饿汉,线程安全)
//对象是方法被调用时,才初始化,也叫做对象的延时加载。称为:懒汉式。
public class Singleton{ private static Singleton instance = new Singleton(); private Singleton () { } public static Singleton getInstance() { return instance; } }
代码可以看出,讲构造函数私有化,并且在类中创建一个本类对象,在类中写一个方法获取到本类对象。
优点:这种写法比较简单,就是在类装载的时候就完成实例化。避免了线程同步问题。
缺点:在类装载的时候就完成实例化,没有达到懒加载的效果。如果从始至终从未使用过这个实例的话,则会造成内存的浪费。
第四种静态代码块(饿汉,线程安全)
public class Singleton { private static Singleton instance; static { instance = new Singleton(); } private Singleton() {} public static Singleton getInstance() { return instance; } }
这种方式和上面的方式其实类似,只不过将类实例化的过程放在了静态代码块中,也是在类装载的时候,
就执行静态代码块中的代码,初始化类的实例。优缺点和上面是一样的。
第五种双重检查(可以用)
public class Singleton { private static volatile Singleton singleton; private Singleton() {} public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; } }
Double-Check概念对于多线程开发来说不会陌生,就像代码中一张,我们进行了两次if (singleton == null)检查,这样就可以保证线程安全了。有人问怎么保证安全的呢?其实我们实例化代码执行一次后,后面再次访问时,判断第一个if (singleton == null)的时候因为不是null,所以不用走同步的 synchronized (Singleton.class) 直接return实例化对象。就可以了
所以这种方法线程安全;延迟加载;效率较高。
第六种静态内部类(可以用)
public class Singleton { private Singleton() {} private static class SingletonInstance { private static final Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonInstance.instance ; } }
其实这种和饿汉式有点一样又不咋像,都是用类装载的机制来保证初始化实例时只有一个线程,但是饿汉式加载就实例化了,没有懒加载,这种静态内部类就是在类加载不回实例化
需要实例的时候调用getInstance,然后为我们返回一个内部类实例的Singleton。
忘记说第七种了,其实就是一种懒汉,像第二种同步方法,这种就同步代码块,都是效率低,不建议使用的。
打卡2018/11/16 博主是个实习的小白,每天积累一点,欢迎大家指正评论,一起加油!