ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

单例模式

2022-07-15 09:31:29  阅读:114  来源: 互联网

标签:Singleton singleton 模式 实例 线程 单例 static


简介

​ 这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式,这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

注意

  • 单例类只能有一个实例;
  • 单例类必须自己创建自己的唯一实例;
  • 单例类必须给所有其他对象提供这一实例;

作用:某个类在整个系统中只能有一个实例对象可以被获取和使用

优点

  • 只生成一个实例,减少系统性能开销;
  • 可以在系统设置全局访问点,优化共享资源访问;

缺点

  • 没有接口
  • 不能继承
  • 与单一职责原则冲突
  • 一个类应该只关心内部逻辑,而不关心外面怎么样来实例化

使用场景

​ 单例模式保证了系统内存中该类只存在一个对象,节省了系统资源。对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能,(比如工具类对象、频繁访问数据库或文件的对象)

注意:当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new;


synchronized关键字

在Java中,synchronized锁可能是我们最早接触的锁了

synchronized的作用

  1. 锁住类
  2. 锁住对象实例

synchronized的3个用法

  1. 静态方法加上关键字:那么它获取的就是这个类的锁,锁住的就是这个类
  2. 实例方法(也就是普通方法)加上关键字:那么它获取的就是这个累的锁,锁住的就是这个对象实例
  3. 方法中使用同步代码块(性能好)

volatile关键字

volatileJava提供的一种轻量级的同步机制,在并发编程中,它也扮演着比较重要的角色同synchronized相比(synchronized通常称为重量级锁),volatile更轻量级。

可见性

所谓可见性,是指当一条线程修改了共享变量的值,新值对于其他线程来说是可以立即得知的。很显然,上述的例子中是没有办法做到内存可见性的。


实现

方式

  1. 饿汉式(线程安全,调用效率高,不能延时加载)
  2. 懒汉式(线程安全,调用效率不高,能延时加载)
  3. 懒汉式-双重检查锁式(JVM底层内部模型原因,偶尔会出问题)
  4. 静态内部类式(线程安全,调用效率高,能延时加载)
  5. 枚举单例(线程安全,调用效率高,不能延时加载)

饿汉式

class Singleton{
    //饿汉式,类加载的时候就进行初始化,避免了线程的同步问题
	private static final Singleton singleton = new Singleton();
	private Singleton() {} //只能在当前类访问它,不能被继承,不能被其他程序用new创建实例对象
    public static Singleton getSingleTon(){
        return singleton;
    }
}

优点:写法简单

缺点:如果从未使用过这个实例,则会造成内存的浪费,也没有达到延迟加载的效果

懒汉式

class Singleton{
	private static Singleton singleton;
	private Singleton() {} //将构造器 私有化,防止外部调用    
	//懒汉式,在第一次调用的时候,即getInstance()方法才进行初始化
	public synchronized static Singleton getInstance() {
		if (singleton ==null) {   //如果为空,创建本实例
			singleton\=new Singleton();
		}
		return singleton;
	}
}

优点:起到了延迟加载的效果,但只能在单线程下使用

缺点:如果在多线程下,一个线程进入了if (singleton == null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例。所以 在多线程环境下不可使用这种方式;

懒汉式-双重检查锁式

在双重检查锁中,代码会检查两次单例类是否有已存在的实例

一次加锁,一次不加锁,一次确保不会有多个实例被创建

class Singleton{
	//为了解决访问的是一个初始化未完成的对象,用volatile关键字修饰
    //使用了关键字后,重排序被禁止,所有的写操作都将发生在读操作之前
	private volatile static Singleton singleton;
	private Singleton() {}
	public static Singleton getInstance() {
        if (null == singleton) {  //先判断对象是否已经被初始化,再决定要不要加锁
		synchronized (Singleton.class) {
			if (null == singleton) {
				singleton =new Singleton();
			}
		}
       }
       return singleton;
	}
}

优点:在浪费性能的情况下,解决了在多线程的情况下,这样写可能会导致singleton有多个实例

静态内部类式

//懒汉式:静态内部类形式
public class SingleTon {
    private SingleTon(){}
    private static class Inner{
        private static final SingleTon SINGLE_TON = new SingleTon();
    }
    
    public static SingleTon getSingleTon(){
        return Inner.SINGLE_TON;
    }
}

优点:避免了线程不安全,利用静态内部类特点实现延迟加载,效率高

缺点:在类进行初始化时,别的线程是无法进入的

枚举单例

借助JDK1.5中添加的枚举来实现单例模式

/*
* 枚举类型:表示该类型的对象是有限的几个
* 我们可以限定为一个,就成了单例
*/
public enum SingleTon {
    INSTANCE;
}

优点:不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象

标签:Singleton,singleton,模式,实例,线程,单例,static
来源: https://www.cnblogs.com/KeFeng/p/16480168.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有