生活就要奋斗
单例模式,按目的来分属于创建型模式。是指一个类只有一个实例,该实例对象必须由该单例类自行创建。其特点:1.构造器私有化;2.只有一个实例对象;3.由单例类自行创建;4.对外提供一个全局的访问方法。目的为了节省内存资源、保证数据内容的一致性。直接看代码,代码中注释,简便易懂,如下:
<一>懒汉式单例模式:
/**
* 懒汉式单例:类加载时不生成实例对象,第一次去调用getInstance()方方法时,才去创建实例对象。
*/
public class LazySingleton {
/* 实例对象 */
private static LazySingleton instance;
/* 构造器私有 */
private LazySingleton() {
}
/* 对外提供获取单例实例的全局访问方法 */
public static void getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
}
// 以下是懒汉式单例模式的变种:保证线程安全,但每次访问都要同步,影响性能,消耗更多的资源。
private static volatile LazySingleton instanceVariant;
public static synchronized void getInstanceVariant() {
if (instance == null) {
instance = new LazySingleton();
}
}
}
<二>饿汉式单例模式:
/**
* 饿汉式单例:类一旦加载就初始化实例,是线程安全的;
* 但容易产生垃圾(当没有调用这个实例时,由于该单例在类创建的同时就初始化了一个静态的对象,所以容易造成内存空间的浪费)
*/
public class HungrySingleton {
/* 实例对象 */
private static final HungrySingleton instance = new HungrySingleton();
/* 构造器私有 */
private HungrySingleton() {
}
/* 供外部调用的方法 */
public static HungrySingleton getInstance() {
return instance;
}
}
<三>双重校验锁单例模式:
/**
* 双重校验锁单利:线程安全,延迟初始化
*/
public class DoubleLockSingleton {
/* volatile关键字能够禁止指令重排,保证在写操作没有完成之前不能调用读操作 */
private static volatile DoubleLockSingleton instance;
/* 构造器私有化 */
private DoubleLockSingleton() {
}
/* 双重检验:第一次避免进入锁,减少性能开销;第二次进行同步,避免多线程问题,防止生成多个对象;
* 由于JVM中创建对象可能导致重排序,在多线程访问下会存在问题,使用volatile修饰变量,禁止指令重排,有效解决这个问题 */
private static DoubleLockSingleton getInstance() {
if (instance == null) {
synchronized (DoubleLockSingleton.class) {
if (instance == null) {
instance = new DoubleLockSingleton();
}
}
}
return instance;
}
}
<四>静态内部类单例模式:
/**
* 静态内部类单例:充分利用了静态内部类的特点。只有第一次调用getInstance()方法时,
* JVM才加载内部类实例化instance对象,只有一个线程可以获取对象的初始化锁,保证单例对象唯一,是线
* 程安全的。这也是目前比较推荐的方式。
*/
public class StaticInnerSingleton {
/* 构造器私有 */
private StaticInnerSingleton() {
}
/* 静态内部类:在此创建单例对象 */
private static class SingletonInstance {
private static final StaticInnerSingleton instance = new StaticInnerSingleton();
}
/* 对外提供获取单例实例的全局访问方法 */
public static StaticInnerSingleton getInstance() {
return SingletonInstance.instance;
}
}
<五>枚举单例模式:
/**
* 枚举单例:是线程安全的。充分利用了枚举的特性,简单且高效。
* 实际开发中枚举单例模式还是用到的比较少
*/
public enum EnumerateSingleton {
INSTANCE;
/* 可以省略此方法,通过Singleton.INSTANCE进行操作*/
public static EnumerateSingleton getInstance() {
return EnumerateSingleton.INSTANCE;
}
}
注:欢迎指教!