单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
意图: 保证一个类仅有一个实例,并提供一个访问它的全局访问点。
主要解决: 一个全局使用的类频繁地创建与销毁。
何时使用: 当您想控制实例数目,节省系统资源的时候。
如何解决: 判断系统是否已经有这个单例,如果有则返回,如果没有则创建。
关键代码: 构造函数是私有的。
应用实例:
优点:
缺点: 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
使用场景:
创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
注意事项: getInstance()方法中需要使用同步锁 synchronized (Single.class) 防止多线程同时进入造成 instance 被多次实例化。
单例也分为 懒汉模式(线程不安全)和饿汉模式(线程安全)
区别就是:
懒汉模式第一次调用的时候才创建对象
而饿汉模式 是在类加载的时候就创建了对象
使用场景 :
懒汉模式 就是什么时候需要他的时候在创建对象 而饿汉模式就是在程序加载的时候就创建此对象
//单例 饿汉模式
public class Single {
//创建 Single 的对象
private static Single instance = new Single();
//让构造函数为 private,这样该类就不会被实例化
private Single(){}
//获取唯一可用的对象
public static Single getInstance(){
return instance;
}
public void show(){
System.out.println("我是单例:饿汉模式");
}
}
测试
public class test {
public static void main(String[] args) {
Single obj = Single.getInstance();
obj.show();
}
}
可以看出来为什么线程是安全的: 因为 在类加载的时候就已经创建了对象 没有多个线程 资源抢占这一回事
//单例 懒汉模式
public class Single {
private static Single instance;
private Single (){}
public static Single getInstance() {
//如果instance 为空那么就创建一个对象
if (instance == null) {
instance = new Single();
}
return instance;
}
public void show(){
System.out.println("我是单例:懒汉模式");
}
}
注意: 上代码 在单线程中 是没有问题 但是在多线程中 就会出现 资源抢占问题
比如对个线程同时 访问getInstance()方法 那么 在 if (instance == null) 绝大部分线程都没有被拦截住
因为 new Single() 是需要时间的 在这个时间内 instance == null 而不是instance != null 所以导致了
private static Single instance; 被来回的覆盖 导致数据丢失
比如: 线程1和线程2 线程1 执行 new Single();的时候线程2也进来了 那么如果在线程2 new Single(); 之前线程1 对 Single 对象内 数据 进行 修改 那么当 线程2 new Single(); 成功之后 就会将 线程1给覆盖了 也就导致线程1 数据丢失
解决办法 使用线程中的同步代码块 synchronized
可能有些人会想 直接在 这样 public static synchronized Single getInstance() 当然这样是可以的 但是影响性能
最佳方式 双重校验锁
这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
//单例 懒汉模式
public class Single {
private volatile static Single instance;
private Single (){}
public static Single getInstance() {
//如果instance 为空那么就创建一个对象
if (instance == null) {
synchronized(Single.class){
if (instance == null) {
instance = new Single();
}
}
}
return instance;
}
public void show(){
System.out.println("我是单例:懒汉模式");
}
}
public class test {
public static void main(String[] args) {
Single obj = Single.getInstance();
obj.show();
}
}
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/weixin_45203607/article/details/120236720
内容来源于网络,如有侵权,请联系作者删除!