单利模式应该是开发中用的最多的一种。
单例设计模式目的:控制特定的类只产生一个对象,当然也允许在一定的情况下灵活改变对象的个数。
实现单例模式的实现:一个类的对象的产生是有类的构造函数完成的,如果想限制对象的产生,可将构造函数变为私有的(至少是受保护的),使得外面的类不能通过引用产生对象;同时为了保护类的可用性,就必须提供一个自己的对象以及访问这个对象的静态方法。
代码体现:
- 将构造函数私有化
- 在类中创建一个本类对象
- 提供一个方法,可以获取到该对象
方式一:饿汉式
//饿汉式 class Single { private Single(){}; private static Single s = new Single(); public static Single getInstance() { //return new Single(); // 这样其实是每一次都创建一个新对象,不要混淆 return s; } } class Test { public static void main(String[] args) { Single ss = Single.getInstance(); } }
方式二 :懒汉式
//懒汉式 class Single { private Single(){}; private static Single s = null; public static Single getInstance() { if(s == null) s = new Single(); return s; } } classTest { public static void main(String[] args) { Single ss = Single.getInstance(); } }
单例模式的两个优势:
1、减少创建java实例所带来的系统开销; 2、便于系统跟踪单个java实例的生命周期和实现状态等;
单例模式使用场景如下:
1、要求生产唯一序列号的环境。 2、在整个项目中需要一个共享访问点和共享数据。 3、需要定义大量的静态常量和静态方法(如工具类)的环境,可以采用单例模式。 4、创建一个对象需要消耗的资源过多,如果访问IO和数据库等资源。
小结:
饿汉式:Single一进内存就创建好了对象
懒汉式:Single进内存还没有存在,只有调用了getInstance方法时才建立对象
懒汉式是延迟加载
懒汉式延迟加载存在的问题: 如果多线程访问时会有线程安全问题
解决方案:
可以加同步来解决,加同步的方式用同步函数和同步代码块都行,但是稍微有些低效
用双重判断的方式能解决低效问题,稍微提高一点
此时同步的时候加的锁是:
该类所属的字节码对象
//懒汉式+多线程 class Single { private Single(){}; private static Single s = null; public static Single getInstance() { if (s==null) { synchronized(Single.class) { if (s==null) { s = new Single(); } } } } } class Test { public static void main(String[] args) { Single ss = Single.getInstance(); new Thread(ss).start(); new Thread(ss).start(); } }