单例模式
单例模式
package singleton.type1; /*所谓单例设计模式,就是采取一定的方法在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得该对象实例的方法 * */ public class SingleTest01 { public static void main(String[] args) { /*饿汉式*/ Singleton instance = Singleton.getInstance(); Singleton instance1 = Singleton.getInstance(); System.out.println(instance==instance1); System.out.println(instance.hashCode()); System.out.println(instance1.hashCode()); } } /*优缺点分析 * 优点:写法比较简单,就是在类装载的时候就完成了实例化。避免了线程同步问题 * 缺点:在类装载的时候完成了实例化,没有达到LZAY LOADING的效果,如果从始至终从未使用过这个实例,则会造成内存的浪费 * */ /*饿汉式(静态变量)*/ class Singleton{ // 1.构造器私有化,外部不能new private Singleton(){ } // 2.本类内部创建一个成员变量,用它来实例对象 private final static Singleton instance=new Singleton(); // 3.提供一个共有的静态方法得到实例对象 public static Singleton getInstance(){ return instance; } }
package singleton.type2; /*所谓单例设计模式,就是采取一定的方法在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得该对象实例的方法 * */ public class SingleTest02 { public static void main(String[] args) { /*饿汉式*/ Singleton instance = Singleton.getInstance(); Singleton instance2 = Singleton.getInstance(); System.out.println(instance==instance2); System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } /*优缺点分析 和上面的静态变量一模一样 * 优点:写法比较简单,就是在类装载的时候就完成了实例化。避免了线程同步问题 * 缺点:在类装载的时候完成了实例化,没有达到LZAY LOADING的效果,如果从始至终从未使用过这个实例,则会造成内存的浪费 * */ /*饿汉式(静态代码块)*/ class Singleton{ // 1.构造器私有化,外部不能new private Singleton(){ } // 2.本类内部创建一个成员变量,用它来实例对象 private static Singleton instance; //在静态代码块中。创建单例对象 static { // 这里直接instance代表上面的instance,否则空指针 instance=new Singleton(); } // 3.提供一个共有的静态方法得到实例对象 public static Singleton getInstance(){ return instance; } }
package singleton.type3; public class SingleTest03 { public static void main(String[] args) { /*饿汉式*/ singleton.type3.Singleton instance = singleton.type3.Singleton.getInstance(); singleton.type3.Singleton instance2 = singleton.type3.Singleton.getInstance(); System.out.println(instance==instance2); System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } /*懒汉式*/ /*提供一个静态的共有方法。当使用到该方法时,才去创建instance*/ /*优缺点 优点:起到了懒加载的效果,但只能在单线程下使用 缺点:在多线程下,会产生多个实例 不推荐使用 * */ class Singleton{ private Singleton(){ } private static Singleton instance; public static Singleton getInstance(){ if(instance==null){ instance=new Singleton(); } return instance; } }
package singleton.type4; public class SingleTest04 { public static void main(String[] args) { /*饿汉式*/ Singleton instance = Singleton.getInstance(); Singleton instance2 = Singleton.getInstance(); System.out.println(instance==instance2); System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } /*懒汉式*/ /*提供一个静态的共有方法。当使用到该方法时,才去创建instance*/ /*针对前面一种给出常识的改进*/ /*优缺点 优点:解决了线程不安全问题 缺点:效率太低了,只执行一次实例化代码就可以了,不需要每次进行同步,下一次就直接返回对象实例就可以了 不推荐使用 * */ class Singleton{ private Singleton(){ } private static Singleton instance; public static synchronized Singleton getInstance(){ if(instance==null){ instance=new Singleton(); } return instance; } } /*加在方法上 以及 加在判断语句里面 syschronized 都没有解决这个问题*/
package singleton.type5; public class SingleTest05{ public static void main(String[] args) { /*饿汉式*/ Singleton instance = Singleton.getInstance(); Singleton instance2 = Singleton.getInstance(); System.out.println(instance==instance2); System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } /*懒汉式*/ /*提供一个静态的共有方法。当使用到该方法时,才去创建instance*/ /*针对前面一种给出常识的改进*/ /*这种同步不同实现线程同步的作用,会产生多个实例*/ /*优缺点 优点:解决了线程不安全问题 缺点:效率太低了,只执行一次实例化代码就可以了,不需要每次进行同步,下一次就直接返回对象实例就可以了 不能使用 * */ class Singleton{ private Singleton(){ } private static Singleton instance; public static Singleton getInstance(){ if(instance==null){ synchronized(Singleton.class) { instance = new Singleton(); } } return instance; } } /*加在方法上 以及 加在判断语句里面 syschronized 都没有解决这个问题 * 前者效率低 后面线程不安全*/
package singleton.type6; public class SingleTest06 { public static void main(String[] args) { /*饿汉式*/ Singleton instance = Singleton.getInstance(); Singleton instance2 = Singleton.getInstance(); System.out.println(instance==instance2); System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } /*懒汉式*/ /*提供一个静态的共有方法。当使用到该方法时,才去创建instance*/ /*针对前面一种给出常识的改进*/ /*双重检查 推荐使用 确保线程安全 延时加载 效率高 * */ class Singleton{ private Singleton(){ } /*volatile的作用*/ private static volatile Singleton instance; public static synchronized Singleton getInstance(){ if(instance==null){ synchronized (Singleton.class){ if(instance==null){ instance=new Singleton(); } } } return instance; } } /*加在方法上 以及 加在判断语句里面 syschronized 都没有解决这个问题*/
package singleton.type7; public class SingleTest07 { public static void main(String[] args) { /*饿汉式*/ Singleton instance = Singleton.getInstance(); Singleton instance2 = Singleton.getInstance(); System.out.println(instance==instance2); System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } /*懒汉式*/ /*提供一个静态的共有方法。当使用到该方法时,才去创建instance*/ /*针对前面一种给出常识的改进*/ /*静态内部类 外部类被装载,内部类还没被装载 在调用方法时内部类会被装载而且装载一次,线程安全的 推荐使用 确保线程安全 延时加载 效率高 * */ class Singleton{ private Singleton(){ /*jvm在装载类的时候是线程安全的,利用了这个特性*/ } private static volatile Singleton instance; private static class SingletonInstance{ private static final Singleton INSTANCE = new Singleton(); } /*提供一个静态的共有方法*/ public static synchronized Singleton getInstance(){ return SingletonInstance.INSTANCE; } }
package singleton.type8; import org.w3c.dom.ls.LSOutput; public class SingleTest08 { public static void main(String[] args) { //饿汉式 Singleton instance = Singleton.INSTANCE; Singleton instance1 = Singleton.INSTANCE; System.out.println(instance==instance1); System.out.println(instance.hashCode()); System.out.println(instance1.hashCode()); instance.sayOK(); } } /*懒汉式*/ /*提供一个静态的共有方法。当使用到该方法时,才去创建instance*/ /*针对前面一种给出常识的改进*/ /*枚举.推荐使用,不仅能避免多线程同步问题,还可以防止反序列化重新创建新的对象 * */ enum Singleton{ INSTANCE; public void sayOK(){ System.out.println("ok"); } } /*推荐饿汉式 枚举 静态内部类 懒汉式双重检查 一共5种方式 * 饿汉式你能确保一定使用*/ /*java.lang.Runtime就是经典的单例模式*/ /*单例模式保证了系统内存中该类只存在一个对象,节省了系统空间,对于一些需要频繁创建和销毁的对象, 使用单例模式可以提高系统性能 想实例化一个单例类的对象时,必须记住使用相应的获取该对象的方法,而不是使用new 单例模式使用的场景:需要频发的创建和销毁对象,但又要经常使用的对象。工具类对象,频繁使用数据库或者文件 的对象,比如数据源 session工厂等*/
自己被加载时就将自己实例化,称为饿汉式单例类
第一次被引用时,才会将自己实例化,称为懒汉式单例类