Java 单例模式

单例模式:

保证一个类只有一个实例,并且提供一个访问该实例的全局访问点

因为只产生一个实例,减少了系统实例开销,当一个对象的产生需要比较多的资源时,如读取配置,产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例对象,然后永久驻留内存的方式解决

一.概念

1.需要生成唯一序列的环境

2.需要频繁实例化然后销毁的对象。

3.创建对象时耗时过多或者耗资源过多,但又经常用到的对象。

4.方便资源相互通信的环境

5.单例类只能有一个实例。
6.单例类必须自己自己创建自己的唯一实例

7.单例类必须给所有其他对象提供这一实例

8.单例类必须自己自己创建自己的唯一实例

9.单例类必须给所有其他对象提供这一实例

Java 单例模式有五种实现方式:

1.饿汉式

2.懒汉式

3.Double CheckLock实现单例

4.静态内部类模式

5.枚举类

二.饿汉式

特点:线程安全,调用效率高,但是不能延时加载

public class Demo1 {

实例化这个类

private static final Demo1  instance=new Demo1 ();

隐藏构造器(或者叫私有构造器)

Private Demo1(){

}

创建静态工厂方法,让外部可以获取实例

 public static Demo1 getInstance (){

         return instances;     

}

}

俄汉式单例设计模式代码中,static变量会在类加载时初始化,此时不会设计多个线程对象访问该对象的问题,虚拟机保证只会装载一次该类,肯定不会发生并发访问的问题,因此,可以省略synchronized关键字

三.懒汉式

特点:线程安全,调用效率不高,但是能延时加载

public class Demo2{     

类初始化时,不初始化这个对象(延时加载,真正用的时候再创建)     

private static Demo2 instance;

私有化构造器     

private Demo2 () {

 

    }

   方法同步,调用效率低     

 创建静态工厂方法 ,让外部可以获取实例     

public static synchronized Demo2 getInstance() {

         if (instance == null) {

             instance = new Demo2 ();

         }         return instance;

     }

}

四.Double CheckLock实现单例:

Double CheckLock也就是双重锁判断机制(由于JVM底层模型原因,偶尔会出问题, 不建议使用),是在懒汉式单例上发展而来

public class Demo3{

    private volatile static Demo3 instance;

私有化构造器     

private Demo3 () {

}

 静态工厂方法,双重锁判断机制     public static Demo3 newInstance() {

         if (instance == null) {

             synchronized (Demo3.class) {

                 if (instance == null) {

                     instance = new Demo3 ();

                 }

             }

         }

         return instance;    

 }

}

如果将同步内容下放到if内部,提高了执行i效率,不必每次获取对象时进行同步,只有第一次才同步创建以后就没有必要了

由于编译器优化和JVM底层内部模型原因,偶尔会出问题,不建议使用

五.静态内部类模式

特点:线程安全,调用效率高,可以延时加载

public class Demo4 {

    静态内部类

         public static class Demo4ClassInstance

         {

                  private static final Demo4 instance = new Demo4();

         }

         私有化构造器

         private Demo4()

         {

         }

         静态工厂方法

         public static Demo4 getInstance()

         {

                  return Demo4 ClassInstance.instance;

         }

}

外部类没有static属性,则不会像俄汉式那样立即加载对象

只有真正调用getInstance(),才会加载静态内部类。加载类时是线程安全的。instance是static final 类型,保证了内存中只有这样一个实例存在,而且只能被赋值一次,从而保证线程安全性

六.枚举类:

特点:线程安全,调用效率高,不能延时加载,可以天然的防止反射和反序列化调用

public class Demo5{

私有化构造器     

private Demo5 (){

}     

使用枚举     

private static enum Singleton{         

instance;

        private Demo5 singleton;

         JVM会保证此方法绝对只调用一次         

private Singleton(){

             singleton = new Demo5 ();

         }         

public Demo5 getInstance(){

             return singleton;

         }

     }

静态工厂方法     

public static Demo5getInstance()

{

 return Singleton.instance.getInstance();    

 }

}

实现简单,枚举本身就是单例模式。由于JVM提供保障避免通过反射和反序列化的漏洞

无延时加载

输出:

结果:

如何选择使用:

单例对象占用资源少,不需要延时加载时:枚举 好于 饿汉 单例对象占用资源多,需要延时加载时:静态内部类 好于 懒汉式

  • 3
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值