单例模式
简介
单例模式保证内存中对象只存在一个实例
单例模式分为饿汉式和懒汉式
饿汉式
- 特点
- 当类被加载到内存时,就会实例化对象,保证JVM线程安全
- 缺点:不管使不使用,类加载时就会实例化
懒汉式
- 特点
- 按需加载,类尽管被加载到内存中,但不会立刻被实例化
- 第一次使用时会实例化,以后便存在内存中
- 缺点:多线程访问时,可能会创建多个实例
8种单例模式
第一种 饿汉式
/**
* 单例模式:保证内存中只有一个实例
* 饿汉式
* 类加载到内存后,就实例化一个单例,JVM保证线程安全
* 简单使用,推荐使用
* 唯一缺点:不管使不使用,类加载时就完成实例化
*/
public class Mgr1 {
private static final Mgr1 INSTANCE = new Mgr1();
/**
* 阻止外部创建实例对象
*/
private Mgr1(){}
public static Mgr1 getInstance(){
return INSTANCE;
}
}
第二种 饿汉式:在静态块中实例化对象
/**
* 单例模式:保证内存中只有一个实例
*/
public class Mgr2 {
private static final Mgr2 INSTANCE;
static {
INSTANCE = new Mgr2();
}
/**
* 阻止外部创建实例对象
*/
private Mgr2(){}
public static Mgr2 getInstance(){
return INSTANCE;
}
}
第三种 懒汉式
/**
* 懒汉式lazy loading
* 按需实例化(第一次使用时才实例化),却带来了线程不安全问题(多个实例)
*/
public class Mgr3 {
private static Mgr3 INSTANCE;
/**
* 阻止外部创建实例对象
*/
private Mgr3(){}
public static Mgr3 getInstance(){
if(INSTANCE == null){
INSTANCE = new Mgr3();
}
return INSTANCE;
}
}
第四种 懒汉式:在方法上加锁,保证线程安全,但降低了效率
/**
* 懒汉式lazy loading
* 按需实例化(第一次使用时才实例化),却带来了线程不安全问题(多个实例)
* 加锁解决线程安全问题,但是会降低效率
*/
public class Mgr4 {
private static Mgr4 INSTANCE;
/**
* 阻止外部创建实例对象
*/
private Mgr4(){}
public static synchronized Mgr4 getInstance(){
if(INSTANCE == null){
INSTANCE = new Mgr4();
}
return INSTANCE;
}
}
第五种 懒汉式:
/**
* 懒汉式lazy loading
* 按需实例化(第一次使用时才实例化),却带来了线程不安全问题(多个实例)
* 加锁解决线程安全问题,但是会降低效率
*/
public class Mgr5 {
private static Mgr5 INSTANCE;
/**
* 阻止外部创建实例对象
*/
private Mgr5(){}
public static Mgr5 getInstance(){
if(INSTANCE == null){
//该方式不能解决线程安全问题
synchronized(Mgr5.class){
INSTANCE = new Mgr5();
}
}
return INSTANCE;
}
}
第六种 懒汉式:双重检查
/**
* 懒汉式lazy loading
* 按需实例化(第一次使用时才实例化),却带来了线程不安全问题(多个实例)
* 加锁解决线程安全问题,但是会降低效率
* 双重检查会提高效率
*/
public class Mgr6 {
private static volatile Mgr6 INSTANCE;//volatile 防止JVM指令重排
/**
* 阻止外部创建实例对象
*/
private Mgr6(){}
public static Mgr6 getInstance(){
if(INSTANCE == null){
//双重检查
synchronized(Mgr6.class){
if(INSTANCE == null){
INSTANCE = new Mgr6();
}
}
}
return INSTANCE;
}
}
第七种 饿汉式改良版:使用静态内部类持有单例对象,实现懒加载
/**
* 单例模式:保证内存中只有一个实例
* 静态内部类方式
* 加载外部类时,不会加载静态内部类,实现懒加载
*/
public class Mgr7 {
/**
* 静态内部类在外部类加载时不会被加载
*/
private static class Mgr7Holder{
private static final Mgr7 INSTANCE = new Mgr7();
}
/**
* 阻止外部创建实例对象
*/
private Mgr7(){}
public static Mgr7 getInstance(){
return Mgr7Holder.INSTANCE;
}
}
第八种 枚举单例:防止反序列化
/**
* 枚举单例,防止反序列化
*/
public enum Mgr8 {
INSTANCE;
//其他方法
public void m(){}
}
在实际生产过程中,使用最多的还是第一种饿汉式单例模式,饿汉式通过静态内部类的方式实现懒加载的方式也是可以的,因为懒汉式涉及到了同步锁机制,降低了执行效率,所以不建议使用,在实际生产环境中,大家应该按情况选择不同的单例模式
奥里给!
来源:CSDN
作者:HuangGang_clown
链接:https://blog.csdn.net/HuangGang_clown/article/details/104259352