作用
保证一个类只有一个实例,并且提供一个访问实例的全局访问点
饿汉式
public class SingletonInstance1 {
// 声明此类型的变量,并实例化,当该类被加载的时候就完成了实例化并保存在了内存中
private final static SingletonInstance1 instance = new SingletonInstance1();
// 私有化所有的构造方法,防止直接通过new关键字实例化
private SingletonInstance1(){}
// 对外提供一个获取实例的静态方法
public static SingletonInstance1 getInstance(){
return instance;
}
}
简单实用,推荐使用!
唯一缺点:不管用到与否,类装载时就完成实例化,如果实际没调用,则会造成资源浪费!
懒汉式
什么时候用,什么时候初始化对象
方法锁
public class SingletonInstance2 {
// 声明此类型的变量,但没有实例化
private static SingletonInstance2 instance;
// 私有化所有的构造方法,防止直接通过new关键字实例化
private SingletonInstance2(){}
// 对外提供一个获取实例的静态方法,为了数据安全添加synchronized关键字
public static synchronized SingletonInstance2 getInstance(){
if(instance == null){
// 当instance不为空的时候才实例化
instance = new SingletonInstance2();
}
return instance;
}
}
在方法上添加synchronized关键字,保证多线程安全,但对性能的影响比较大
双重检查
public class SingletonInstance3 {
// 声明此类型的变量,但没有实例化
private static volatile SingletonInstance3 instance;
// 私有化所有的构造方法,防止直接通过new关键字实例化
private SingletonInstance3(){}
// 对外提供一个获取实例的静态方法,
public static SingletonInstance3 getInstance(){
if(instance == null){
synchronized(SingletonInstance3.class){
if(instance == null){
instance = new SingletonInstance3();
}
}
}
return instance;
}
}
相比方法锁,通过减小同步代码块的方式提高效率
不加volatile会有什么问题?
实例化的过程
- 分配内存空间
- 执行构造方法,实例化对象
- 把这个对象赋值给这个空间
如果不加volatile,会执行重排序,比如过程变成了132,这个可能导致其它调用拿到的是未完全实例化的对象
静态内部类
public class SingletonInstance4 {
// 静态内部类
public static class SingletonClassInstance{
// 声明外部类型的静态常量
private static final SingletonInstance4 instance = new SingletonInstance4();
}
// 私有化构造方法
private SingletonInstance4(){}
// 对外提供的唯一获取实例的方法
public static SingletonInstance4 getInstance(){
return SingletonClassInstance.instance;
}
}
通过JVM保证单例,加载外部类时不会加载内部类,这样可以实现懒加载
枚举
public enum SingletonInstance5 {
// 定义一个枚举元素,则这个元素就代表了SingletonInstance5的实例
INSTANCE;
}
不仅可以解决线程同步,还可以防止反序列化
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/85463.html