单例设计模式:就是采用一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。
1、饿汉式(静态变量)
package 单例; public class 饿汉式_静态常量 { /* * 步骤 * 1、构造器私有化(防止new) * 2、类的内部创建对象 * 3、向外暴露一个静态的公共方法 */ public static void main(String[] args) { singleton instance=singleton.getinstance(); singleton instance2=singleton.getinstance(); System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } class singleton{ //构造起私有化,外部不能new private singleton() { } //本类内部创建对象实例 private final static singleton instance=new singleton(); //提供一个公共的静态方法 public static singleton getinstance() { return instance; } }
优点:这种写法比较简单,在类装载的时候就完成实例化了,避免了线程同步的问题,
缺点:在类装载的时候就完成了实例化,没有达到懒加载的效果,如果从始至终从未用过这个实例,则会造成内存的浪费
2、饿汉式(静态代码块)
package 单例; public class 饿汉式_静态代码块 { /* * 步骤 * 1、构造器私有化(防止new) * 2、类的内部创建对象 * 3、向外暴露一个静态的公共方法 */ public static void main(String[] args) { singleton instance=singleton.getinstance(); singleton instance2=singleton.getinstance(); System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } class singleton{ //构造起私有化,外部不能new private singleton() { } //本类内部创建变量 private static singleton instance; static {//在静态代码快中创建单例对象 instance=new singleton(); } //提供一个公共的静态方法 public static singleton getinstance() { return instance; } }
优点缺点和上一个一样。
3、双重检查
package 单例; public class 双重检查 { /* * 步骤 * 1、构造器私有化(防止new) * 2、类的内部创建对象 * 3、向外暴露一个静态的公共方法 */ public static void main(String[] args) { singleton instance=singleton.getinstance(); singleton instance2=singleton.getinstance(); System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } class singleton{ //构造起私有化,外部不能new private singleton() { } //本类内部创建变量 private static volatile singleton instance; //提供一个公共的静态方法,加入双重检查代码,解决线程安全问题 //同时解决懒加载问题 public static singleton getinstance() { if(instance==null) { synchronized (singleton.class) { if(instance==null) { instance=new singleton(); } } } return instance; } }
优点:线程安全,延迟加载,效率极高
4、静态内部类
静态内部类的特点:
- 外部类被装载的时候内部类不会被装载
- 调用静态方法时会装载一次(仅一次)内部类
package 单例; public class 静态内部类 { /* * 步骤 * 1、构造器私有化(防止new) * 2、类的内部创建对象 * 3、向外暴露一个静态的公共方法 */ public static void main(String[] args) { singleton instance=singleton.getinstance(); singleton instance2=singleton.getinstance(); System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } class singleton{ //构造起私有化,外部不能new private singleton() { } //本类内部创建变量 private static volatile singleton instance; //写一个静态内部类,类中有一个静态属性 private static class sin{ private static final singleton INSTANCE=new singleton(); } //提供一个公共的静态方法,直接返回sin.INSTANCE public static singleton getinstance() { return sin.INSTANCE; //jvm在装载类的时候是线程安全的 } }
优点:
- 这种方式采用了类装载的机制来保证初始化实例时只有一个线程
- 类的静态属性只会在第一次加载类的时候初始化,jvm保证了线程的安全性,在类的线程是无法进入的
5、枚举
package 单例; public class 枚举 { public static void main(String[] args) { singleton instance=singleton.INSTANCE; singleton instance2=singleton.INSTANCE; System.out.println(instance.hashCode()); System.out.println(instance2.hashCode()); } } enum singleton{ INSTANCE; public void sayOK() { System.out.println("OK"); } }
优点:线程安全,还能防止反序列化重新创建新的对象