什么是单例?:其定义是单例对象的类只能允许一个实例存在
单例的实现基本原理:1.将该类的构造方法定义为私有访问,不对外暴露从而使其他类不能实例化该类对象,只能通过该类的静态方法得到该类的唯一实例 2.在该类中定义一个静态方法(getInstance),当我们调用该方法时返回该类的实例对象
几种实现方式:
饿汉式单例模式:
/**
- 饿汉式静态常量式单例模式
- 优点:这种写法在JVM装载类的时候就实例化了,避免了线程同步的问题
- 缺点:在类装载的时候就实例化,没有达到延时加载的效果,造成内存浪费
- @author zhuys
*/
public class HungrySinglton {
//使用经常常量初始化实例
private final static HungrySinglton hungrySinglton = new HungrySinglton();
// 使用静态块初始化类的实例,与上面效果一致
// private static HungrySinglton hungrySinglton;
// static {
// hungrySinglton = new HungrySinglton();
// }
private HungrySinglton() {};
public static HungrySinglton getInstance() {
return hungrySinglton;
}
}
懒汉式单例模式(非同步):
/**
- 懒汉式单例模式:非同步
- 优点:在调用的时候初始化该单例
- 缺点:并非线程同步,不建议使用
- @author zhuys
*/
public class LazySingleton {
private static LazySingleton lazySingleton;
private LazySingleton() {};
public static LazySingleton getInstance() {
if(lazySingleton == null) {
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
懒汉式单例(同步):
/**
- 懒汉式单例模式:同步
- 优点:在调用的时候初始化该单例并实现线程同步
- @author zhuys
*/
public class LazySyncSingleton {
private static LazySyncSingleton lazySingleton;
private LazySyncSingleton() {};
//法1:该方式使用synchronized同步锁将整个方法同步 实现线程同步 但同步整个方法在高并发的情况下会造成阻塞
//效率低下,不推荐使用
public static synchronized LazySyncSingleton getInstance1() {
if(lazySingleton == null) {
lazySingleton = new LazySyncSingleton();
}
return lazySingleton;
}
//法2:使用synchronized同步实例化改单例的代码块;但该方法不能完全实现同步,可能会产生多个实例;例如:在第一次创建时
//多个线程同时进入if(lazySingleton == null) 则会产生多个实例 不推荐使用
public static LazySyncSingleton getInstance2() {
if(lazySingleton == null) {
synchronized (LazySyncSingleton.class) {
lazySingleton = new LazySyncSingleton();
}
}
return lazySingleton;
}
//法3:双重检查法,同步代码块中再次检查一次是否w为null解决了上述问题 推荐使用
public static LazySyncSingleton getInstance3() {
if(lazySingleton == null) {
synchronized (LazySyncSingleton.class) {
if(lazySingleton == null) {
lazySingleton = new LazySyncSingleton();
}
}
}
return lazySingleton;
}
}
内部类单例模式:
package pers.ly.learn.designModel.singleton;
/**
- 静态内部类单例模式:
- 静态内部类方式在InnerSingleton类被装载时并不会立即实例化
- 因为静态内部类是在调用的时候才会实例化,这样就达到了延时加载节省资源的效果
- 另外在静态内部类中通过静态常量初始化该单例又到达了保证其唯一性的效果
- 优点:避免了线程不安全,延迟加载,效率高。 推荐使用
- @author zhuys
*/
public class InnerSingleton {
private InnerSingleton() {};
private static class InnerSingletonInstance{
private final static InnerSingleton innerSingleton = new InnerSingleton();
}
public static InnerSingleton getInstance() {
return InnerSingletonInstance.innerSingleton;
}
}