前言
设计模式(Design Pattern)
是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。
开发中的最高境界便是没有设计模式,因为你所编写的每一行代码都自发的趋于最优解。
单例模式
是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。
- 饿汉式
之所以称为饿汉式,是因为对象随着类的加载已经创建的,凸显的比较“饥饿”,仅此而已。
优点:避免了线程安全问题,它是绝对线程安全的。
缺点:很明显,可能容易造成内存浪费,因为对象在类加载时就已经被创建,这是如果暂时用不到,就会造成资源浪费。
//一般方式
class Singleton{
//创建对象(new一次)
private final static Singleton instance = new Singleton();
//私有化构造器
private Singleton(){}
//静态返回
public static Singleton getInstance(){
return instance;
}
}
//静态代码块方式
class Singleton{
//定义但未初始化
private final static Singleton instance;
//私有化构造器
private Singleton(){}
//静态代码块赋值
static {
instance = new Singleton();
}
public static Singleton getInstance(){
return instance;
}
}
- 懒汉式
见名知意,相比饿汉式,它的特点便是,使用时才开始创建,所以比较“懒”。
优点:与饿汉式形成对比,节省内存。
缺点:一般线程不安全,改进扩展后可以。
//懒汉式(线程不安全)
class Singleton{
private static Singleton instance;
//私有化构造器
private Singleton(){}
//多个线程同时调用的话就会new出多个对象
public static Singleton getInstance(){
//多个线程同时进入会判断对象为null
if(instance==null){
//从而创建对个对象 不再是单例
instance = new Singleton();
}
return instance;
}
}
改进:加入同步锁之后,线程安全问题解决,但效率极低
//懒汉式(线程安全 效率低)
class Singleton{
private static Singleton instance;
//私有化构造器
private Singleton(){}
//同步方法 每次只能有一个线程进入
public static synchronized Singleton getInstance(){
//每个线程依次进入进行判断是否为null,效率极低
if(instance==null){
instance = new Singleton();
}
return instance;
}
}
//懒汉式(线程安全 效率低)
class Singleton{
private static Singleton instance;
//私有化构造器
private Singleton(){}
public static Singleton getInstance(){
//同步代码块方式(左右与上述一致 写法不同) 每次只能有一个线程进入
//每个线程依次进入进行判断是否为null,效率极低
synchronized (Singleton.class){
if(instance==null){
instance = new Singleton();
}
}
return instance;
}
}
上述问题:线程安全问题是解决了,但是效率十分低,因为只需要第一个线程进入之后判断是否为null,然后new一个对象,后面的线程进入只需要return返回就行了,如果继续等待同步锁,一次进入,就会造成效率问题。
继续改进:进行双重检验,在第二种的基础上再嵌套一层判空,这样的话除了前几个线程(跟随第一个线程同时进入)需要进入等待之外,其他线程在对象创建完成之后,只在最外层判空就行了(这一步骤是所有之后线程可以同时进行的,故效率高)。
//懒汉式(线程安全 推荐)
class Singleton{
private static volatile Singleton instance;
//私有化构造器
private Singleton(){}
public static Singleton getInstance(){
//同步代码块(双重检查)
if (instance==null){
//这一层只有前几个线程同时进入
//待第一个线程创建对象完成之后,之后的所有线程不会再进入等待
synchronized (Singleton.class){
if(instance==null){
instance = new Singleton();
}
}
}
return instance;
}
}
- 静态内部类
//静态内部类(线程安全 省内存)
利用静态内部类的特殊机制(外层类加载时,内部类即便是静态的,也不会随之加载,这样一来,就不会造成内存浪费,只在调用时创建完成,并且线程是绝对安全的)。
class Singleton{
//私有化构造器
private Singleton(){}
//静态内部类
private static class SingletonInstance{
private static final Singleton instance = new Singleton();
}
//return方法
public static Singleton getInstance(){
return SingletonInstance.instance;
}
}
- 枚举
简单粗暴枚举法
绝对单例,绝对线程安全,绝对不内存浪费
//枚举
enum Singleton{
instance;//属性
}
以上便是我学习过程中总结的一些思想和笔记,大家可以在学习过程中多交流,共同进步。——一个从入门到入土的程序小白。