设计模式-单例模式

设计模式(Design pattern) java开发者必修的一门课程,而设计模式总的来说有很多种,但是当你融汇贯通之后,并不需要去考虑具体的用哪种模式,因为设计会把创建型、行为型和结构型这些模式融合在一起。

首先讲一下单例模式,单例模式:根据名字就能想到只有一个实例,自己负责创建自己的对象,而这个类提供了一种访问其唯一对象的方式,不用实例化,可以直接访问,拿过来用。

单例模式我是把它分为四种:

1、饿汉模式

2、懒汉模式

3、静态内部类

4、枚举


1、饿汉模式

实例在初始化的时候就可以

存在(你在或不在,我都在那里,不离不弃),其实在开发中用这一种本人觉得就够了,浪费一点内存空间不会影响大局(话说你不用的,你装载它干啥)。

优点:线程安全

缺点:浪费内存空间

代码:

/**
 * 饿汉式
 * 类加载到内存后,就实例化一个单例,JVM保证线程安全
 * 简单实用,推荐使用!
 * 唯一缺点:不管用到与否,类装载时就完成实例化
 * 
 */
public class Mgr01{
    private static final Mgr01 INSTANCE = new Mgr01();

    private Mgr01() {};

    public static Mgr01 getInstance() {
        return INSTANCE;
    }

}

 


2、懒汉模式

顾名思义,懒汉模式,我不用我就不去实例化,等用的时候我再实例化,懒汉模式可分为几种,下面我就一一介绍一下

 (1)按需初始化,但是会带来线程不安全的问题,多个线程访问就会多次初始化(Thread.sleep(1)是为了测试多个线程)

   代码:

/**
 * lazy loading
 * 也称懒汉式
 * 虽然达到了按需初始化的目的,但却带来线程不安全的问题
 */
public class Mgr02 {
    private static Mgr02 INSTANCE;

    private Mgr02() {
    }

    public static Mgr02 getInstance() {
        if (INSTANCE == null) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            INSTANCE = new Mgr02();
        }
        return INSTANCE;
    }

    public void m() {
        System.out.println("m");
    }

}

  (2)按需初始化,方法添加synchronized,这样效率会大大降低,因为每一次都会加锁,线程安全

  代码:

/**
 * lazy loading
 * 也称懒汉式
 * 可以通过synchronized解决,但也带来效率下降
 */
public class Mgr03 {
    private static Mgr03 INSTANCE;

    private Mgr03() {
    }

    public static synchronized Mgr03 getInstance() {
        if (INSTANCE == null) {
            try {
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            INSTANCE = new Mgr03();
        }
        return INSTANCE;
    }

    public void m() {
        System.out.println("m");
    }

}

(3)按需初始化,同步代码块,每次初始化的时候添加synchronized,线程不安全,因为可能多个线程进入判断之后

  代码:

/**
 * lazy loading
 * 也称懒汉式
 * 虽然达到了按需初始化的目的,但却带来线程不安全的问题
 * 妄图通过减小同步代码块的方式提高效率,然后不可行
 */
public class Mgr04 {
    private static Mgr04 INSTANCE;

    private Mgr04() {
    }

    public static Mgr04 getInstance() {
        if (INSTANCE == null) {
            //妄图通过减小同步代码块的方式提高效率,然后不可行
            synchronized (Mgr04.class) {
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                INSTANCE = new Mgr04();
            }
        }
        return INSTANCE;
    }

    public void m() {
        System.out.println("m");
    }

 }   

  (4)*双重检查 这个方式就是懒汉模式的最佳方式,里外全部判断,保证线程安全

  代码:

/**
 * lazy loading
 * 也称懒汉式
 * 双重检查
 * volatile 也要添加,防止指令重排序(DCL单例是否要加volatile的问题)
 */
public class Mgr04 {
    private static volatile Mgr04 INSTANCE; //JIT

    private Mgr04() {
    }

    public static Mgr04 getInstance() {
        if (INSTANCE == null) {
            //双重检查
            synchronized (Mgr04.class) {
                if(INSTANCE == null) {
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    INSTANCE = new Mgr06();
                }
            }
        }
        return INSTANCE;
    }

    public void m() {
        System.out.println("m");
    }
}

 


3、静态内部类单例

加载外部类的时不会加载内部类,也可实现懒加载

优点:线程安全,代码部分不需要加锁,由JVM保证线程安全

缺点:可以被反序列化

代码:

/**
 * 静态内部类方式
 * JVM保证单例
 * 加载外部类时不会加载内部类,这样可以实现懒加载
 */
public class Mgr05 {

    private Mgr05() {
    }

    private static class Mgr05Holder {
        private final static Mgr05 INSTANCE = new Mgr05();
    }

    public static Mgr05 getInstance() {
        return Mgr05Holder.INSTANCE;
    }

    public void m() {
        System.out.println("m");
    }

}

4、枚举

优点:线程安全,防止反序列化

缺点:

代码:

/**
 * 不仅可以解决线程同步,还可以防止反序列化。
 */
public enum Mgr06 {

    INSTANCE;

    public void m() {}

}

个人总结:这几种单例模式,个人建议使用饿汉式,因为我觉得浪费一点内存空间可以接收,如果是一个完美主义者可以用最后一个方式,这样不怕被破解。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值