单例模式的好处?

单例的好处?啥时候不能用单例?

 

 优点:单例模式保证java应用程序中,一个类Class只有一个实例在,使用单例模式好处在于可以节省内存,节约资源,对于一般频繁创建和销毁对象的可以使用单例模式。

 因为它限制了实例的个数,有利于java垃圾回收。好的单例模式也能提高性能。例如:数据库连接池、httpclient连接单例

对于系统中的某些类来说,只有一个实例很重要,Windows中就只能打开一个任务管理器,如何保证一个类只有一个实例并且这个实例易于被访问呢?定义一个全局变量可以确保对象随时都可以被访问,但不能防止我们实例化多个对象。一个更好的解决办法是让类自身负责保存它的唯一实例。这个类可以保证没有其他实例被创建,并且它可以提供一个访问该实例的方法。这就是单例模式的模式动机。

Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。

 

缺点:有的为了节省资源创建单例模式,可能会导致共享连接池的对象程序过多,出现连接池溢出等问题。

         可能会造成一些开发混淆,因为单例模式的不能进行自己实例化。

1.单例的缺点 就是不适用于变化的对象,如果同一类型的对象总是要在不同的用例场景发生变化,单例就会引起数据的错误,不能保存彼此的状态。

2.单例模式的构造函数是静态的,所以在继承单例时,出现问题,不能被子类继承

 

第一种饿汉式:

    public class Singleton {

    private static Singleton instance = new Singleton();

    private Singleton(){};

    public static Singleton getSingletonInstance() {

        return instance;

    }

}

    优点:在类加载初始化的时候就创建对象,调用getInstance的时候,没有同步方法,运行时性能较高。

    缺点:类加载速度慢,占用太多大的资源空间。

 

第二种懒汉式:

  public class Singleton {

    private static Singleton instance = null;

    private Singleton(){};

    public static synchronized Singleton getSingletonInstance() {

        if (instance == null){

            instance = new Singleton();

        }

        return instance;

    }

}

    优点:避免了第一种方式的缺点, 同时,可以在多线程下运行安全。

    缺点:因为他使用了锁,在运行中效率慢。

 

第三种 这种实现方式可以实现既线程安全地创建实例,而又不会对性能造成太大的影响。它只是在第一次创建实例的时候同步,以后就不需要同步了,从而加快了运行速度。

双重检查加锁机制的实现会使用一个关键字volatile,它的意思是:被volatile修饰的变量的值,将不会被本地线程缓存,所有对该变量的读写都是直接操作共享内存,从而确保多个线程能正确的处理该变量。volatile只能保证可见性, 无法保证原子性.

public class Singleton {

    private static volatile Singleton instance = null;

    private Singleton(){};

 

    public static Singleton getSingletonInstance() {

        if (instance == null){

            synchronized (Singleton.class) {

                if(instance == null) {

                    instance = new Singleton();

                }

            }

        }

        return instance;

    }

}

 

第四种 内部类只有在外部类被调用才加载,产生SINGLETON实例;又不用加锁。此模式有上述两个模式的优点,屏蔽了它们的缺点,是最好的单例模式

public class Singleton {

    private Singleton(){};

    public static Singleton getSingletonInstance() {

        return Holder.SINGLETON;

    }

    private static class Holder{

        private static final Singleton SINGLETON = new Singleton();

    }

}

 

1、时间和空间  比较上面两种写法:懒汉式是典型的时间换空间,也就是每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间。当然,如果一直没有人使用的话,那就不会创建实例,则节约内存空间。  饿汉式是典型的空间换时间,当类装载的时候就会创建类实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断了,节省了运行时间。  

 

2、线程安全  (1)从线程安全性上讲,不加同步的懒汉式是线程不安全的,比如,有两个线程,一个是线程A,一个是线程B,它们同时调用getInstance方法,那就可能导致并发问题。如下示例:

通过图5.4的分解描述,明显地看出,当A、B线程并发的情况下,会创建出两个实例来,也就是单例的控制在并发情况下失效了。  (2)饿汉式是线程安全的,因为虚拟机保证只会装载一次,在装载类的时候是不会发生并发的。  (3)如何实现懒汉式的线程安全呢?  当然懒汉式也是可以实现线程安全的,只要加上synchronized即可

 

但是这样一来,会降低整个访问的速度,而且每次都要判断。那么有没有更好的方式来实现呢?

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值