单例模式(Singleton)
单例模式指的是:此类在任何时候都只存在一个对象。
实现步骤:1、构造器私有化。2、提供公共的 获取对象的方法getInstance()。
分类:
饿汉式:在加载类的时候就创建对象。
懒汉式:在使用类的时候才创建对象。
枚举,是 JDK 1.5 中引入的新特性。
实现方式:
1、饿汉式:在加载类的时候,便创建对象。
/** *饿汉式实现单例模式:加载类的时候创建好对象。不能延时加载 */ public class Antts{ //1、类加载的时候线程一定安全 private static Antts instance = new Antts(); //2、构造器私有化 private Antts(){ if(null!=instance) { throw new RuntimeException();//避免通过反射调用构造器 } } //3、对外提供获取对象的方法 public static Antts getInstance() { return instance; } //4、避免通过反序列化获取新对象 public Object readResolve() throws ObjectStreamException{ return instance; } }
2、懒汉式:在使用的时候,创建对象(延时加载),需要给getInstance方法加锁,慢。
/** *懒汉式实现单例模式:要使用对象的时候创建对象(延时加载),需要加锁。 */ public class Antts{ //1、类加载的时候线程一定安全 private static Antts instance; //2、构造器私有化 private Antts(){ if(null!=instance) { throw new RuntimeException();//你干嘛?想通过反射创建新对象? } } //3、对外提供获取对象的方法,为了保证多线程下不出意外,需要加锁。 public static synchronized Antts getInstance() { if(instance==null){ instance = new Antts();//使用的时候创建对象 } return instance; } //4、避免通过反序列化获取新对象 public Object readResolve() throws ObjectStreamException{ return instance; } }
3、懒汉式,但是使用静态内部类创建对象:不需要使用锁,快。
/** * 静态内部类实现单例:类加载的时候不会加载内部类 */ public class Antts{ //1、为了保证不被反射和反序列化创建多个对象,储存一下 private static Antts instance; //静态内部类 private static class Temp{ private static final Antts antts = new Antts(); } //2、构造器私有化 private Antts(){ if(null!=instance) { throw new RuntimeException();//你干嘛?想通过反射创建新对象? } } //3、此时才会加载内部类 public static Antts getInstance() { if(instance==null){ instance=Temp.antts; } return instance; } //4、避免通过反序列化获取新对象 public Object readResolve() throws ObjectStreamException{ return instance; } }
4、懒汉式,但是使用双重检测加锁:使用了synchronized块,volatile声明,保证对象唯一。
class Antts{ //volatile避免指令重排导致 创建多个对象 private static volatile Antts instance; //构造器私有化 private Antts(){ if(instance!=null){ throw new RuntimeException();//你干嘛? } } //提供公共的静态方法获取对象 public static Antts getInstance(){ //双重检测,提高性能。 if(null!=instance){ return instance; } synchronized (Antts.class) { if (instance == null) { //创建一个对象:1、开辟空间。2、初始化对象信息。3、返回对象地址给引用。 instance = new Antts(); } return instance; } } }
5、枚举实现:在加载的时候就创建了,不能延时加载。(了解一下:枚举)
/** * 使用枚举实现单例:这里的Antts.INSTANCE用于只有一个。 */ public enum Antts{ INSTANCE; void doSomething(){ System.out.println("I love her!"); } } class test{ public static void main(String[] args) { Antts.INSTANCE.doSomething(); } }
运行结果: