目录
什么是单例模式
- 单例模式是为确保一个类只有一个实例,并为整个系统提供一个全局访问点的一种模式方法。
我们可以得到以下信息
- 在任何情况下,每个单例类只能有一个实例对象。
- 单例类为整个系统提供者唯一的实例。
[比如在计算机系统里可以连接多个打印机,但是只能有一个管理打印机的池子,来避免两个打印作业输入到一个打印机中。]
饿汉式
* 优点:类装载就完成,简单,避免线程同步 * 缺点:没有达到懒加载,若未使用,内存浪费
1、静态变量创建
/**
* 优点:类装载就完成,简单,避免线程同步
* 缺点:没有达到懒加载,若未使用,内存浪费
* @author Lenovo
*
*/
public class HungrySingleton1 {
//构造器私有化
private HungrySingleton1() {
}
private final static HungrySingleton1 instance = new HungrySingleton1();
public static HungrySingleton1 getInstance() {
return instance;
}
}
2、静态代码块创建
/**
* 优点:类装载就完成,简单,避免线程同步
* 缺点:没有达到懒加载,若未使用,内存浪费
* @author Lenovo
*
*/
public class HungrySingleton2 {
//构造器私有化
private HungrySingleton2() {
}
private static HungrySingleton2 instance;
//静态代码块创建
static {
instance = new HungrySingleton2();
}
public static HungrySingleton2 getInstance() {
return instance;
}
}
上述代码中的一个缺点是该类加载的时候就会直接new 一个静态对象出来,当系统中这样的类较多时,会使得启动速度变慢 。
懒汉式
1、线程不安全的懒汉
/**
* 优点:懒加载
* 缺点:只能在单线程下使用,线程不安全
* @author Lenovo
*
*/
public class LazySingleton1 {
private static LazySingleton1 instance;
private LazySingleton1() {
}
public static LazySingleton1 getInstance() {
if (instance== null) {
instance = new LazySingleton1();
}
return instance;
}
}
2.解决线程安全、但效率低的懒汉式
/**
* 优点:懒加载,解决了线程不安全的问题
* 缺点:效率太低了,执行getInstance需要同步,
* 其实只需要执行一次实例化就OK,剩下的直接return;
* @author Lenovo
*
*/
public class LazySingleton2 {
private static LazySingleton2 instance;
private LazySingleton2() {
}
//1
public static synchronized LazySingleton2 getInstance1() {
if (instance== null) {
instance = new LazySingleton2();
}
return instance;
}
//2
//这种方式实际不能起到线程同步的问题
//若都进入了instance== null,实际还是会产生两个实例
public static LazySingleton2 getInstance2() {
if (instance== null) {
synchronized (instance) {
instance = new LazySingleton2();
}
}
return instance;
}
}
3、双重检查:double-check
/**
* 双重检查:double-check
* 优点:懒加载,解决了线程不安全的问题,实例化代码块只执行一次
* 线程安全、延迟加载、效率较高
* @author Lenovo
*
*/
public class LazySingleton3 {
private static LazySingleton3 instance;
private LazySingleton3() {
}
public static LazySingleton3 getInstance() {
if (instance== null) {
synchronized (instance) {
if (instance== null) {
instance = new LazySingleton3();
}
}
}
return instance;
}
}
静态内部类
借用类加载机制
/**
* 优点:使用类装载机制保障安全,类的静态内部类只会在第一次加载时初始化
* 线程安全(类装载机制保障)、延迟加载、效率高
* @author Lenovo
*
*/
public class StaticInnerClassSingleton {
private StaticInnerClassSingleton() {
}
//不会在外部类加载时加载,会在被使用时加载
private static class Innerclass {
private static final StaticInnerClassSingleton instance = new StaticInnerClassSingleton();
}
public static StaticInnerClassSingleton getInsatnce() {
return Innerclass.instance;
}
}
枚举
借用枚举变量使之单例,而枚举构造又可防止反射创建单例
推荐使用
public class EnumSingleton {
public static void main(String[] args) {
Singeleton singeleton1 = Singeleton.INSTANCE;
Singeleton singeleton2 = Singeleton.INSTANCE;
//实际上:Singleton1 == singleton2
System.out.println(singeleton1 == singeleton2);
//true
}
}
/**
* 优点:避免多线程同步问题,可以防止反序列化重新创建新对象
* 推荐使用
* @author Lenovo
*
*/
enum Singeleton {
INSTANCE;//保障单例
public void sayOk() {
System.out.println("ok!");
}
}