1、懒汉式:需要获取对象的时候再实例化。
/** * 懒汉式。在类中仅仅只是声明,外部需要调用单例时才实例化。 */ public class Singleton{ private static Singleton singleton; //构造器私有化 private Singleton(){ } //注意,记得加同步锁,保证线程安全 public static synchronized Singleton getInstance(){ if(singleton==null) { singleton=new Singleton(); } return singleton; } }
2、饿汉式:直接实例化对象,调用的时候再返回对象。
/** * 饿汉式。在类中实例化,外部调用时直接返回单例。 */ public class Singleton{ private static Singleton singleton=new Singleton(); //构造器私有化 private Singleton(){ } public static Singleton getInstance(){ return singleton; } }
3.线程安全的单例模式
直接使用synchronized锁住方法,效率比较差。
主要使用volatile修饰变量,使用双重检查锁(Double Check Lock)。保证线程安全并提高效率。
public class Singleton{ /** * 懒汉式。先声明,等要用的时候再实例化。 * 使用volatile修饰,保证可见性。 */ private static volatile Singleton singleton=null; private Singleton(){ //.. } /** * 使用双重检查锁,保证线程安全。 * static修饰为静态变量,可以直接通过类名调用。 */ public static Singleton getSingleton() { if(singleton==null) { synchronized(singleton) { if(singleton==null) { singleton=new Singleton(); } } } return singleton; } }
单例模式思考:
1.单例模式有什么用?
节约系统资源,不用一直新建对象。
2.为什么要用static修饰对象?
确保对象的唯一性。内存中始终只有一个实例,而static修饰就保证了这一点,在任何时刻任意类中引用都是唯一一个实例在操作。
3.为什么构造器要用private?
使外部无法访问构造方法,无法通过new实例化,只能调用getInstance()获取实例。
4.为什么要用synchronized修饰?
保证线程安全,数据不会混乱
更详细的资料: