单例模式详解

Posted 3 ERROR(s)

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式详解相关的知识,希望对你有一定的参考价值。

文章目录


前言

一、单例模式的特点?

单例模式是一种常见的设计模式,它有以下特点:

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

单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例,总之,选择单例模式就是为了避免不一致状态

二、饿汉式单例模式

class Singleton 

    //让构造方法变为私有的,在类的外部无法创建对象
        private Singleton()
        
        private static Singleton singleDog=new Singleton();

        public static Singleton getSingleDog()
            return singleDog;
        

饿汉式在类加载的时候就创建好了一个静态的对象提供使用,以后不再改变,所以它天生就是线程安全的。

三、懒汉式单例模式

1.懒汉模式的创建

相比于饿汉模式,懒汉模式只创建我们需要的实例资源,所以他的效率更高!

class Singleton2 
    private Singleton2()

    private static Singleton2 singleton=null;

    public static Singleton2 getSingleton()
        if(singleton==null)
            Singleton2 singleton=new Singleton2();
        
        return singleton;
    

2.懒汉模式的线程不安全问题及解决

懒汉模式线程不安全的原因:

  • 懒汉式单例模式是线程不安全的,他有可能同时生成多个singleton对象。
  • 但是他只有在生成实例对象之前调用getSingleton方法存在线程安全问题。
  • 但是如果实例已经创建好了再去并发调用getSingleton就不会出现线程安全问题。

解决线程不安全问题的几种方法:
方式一:加对象锁

class Singleton2 
    private Singleton2()

    private static Singleton2 singleton=null;

    public static Singleton2 getSingleton()
        synchronized (Singleton2.class)
               if(singleton==null)
            Singleton2 singleton=new Singleton2();
            
        
        return singleton;
    
 

给getSinglenton方法加上对象锁,保证其原子性。
但是这种加锁方式再创建了实例对象之后还会每次加锁解锁操作,浪费了大量的资源!这时候我们就需要更新一下技术了!

方式二:双重检查锁定

class Singleton2 
    private Singleton2()
    //加入volatile关键字避免内存可见性引来的问题
    private volatile static  Singleton2 singleton=null;


    public static Singleton2 getSingleton()

        if (singleton==null)   //多加了一个if判定保证效率!
            synchronized (Singleton2.class)
                if(singleton==null)
                    Singleton2 singleton=new Singleton2();
                
            
        
        return singleton;
    
 

方式三: 静态内部类

public class Lazysingleton 
    //静态内部类
    private static class  LazyHolder
        private  static Lazysingleton instance=new Lazysingleton();
    

    private Lazysingleton()

    //在类加载的时候只创建了一个instance对象,在调用get方法的时候获得该对象。
    public static Lazysingleton getInstance()
        return LazyHolder.instance;
    

既解决了线程安全问题,又解决了浪费资源的问题。

以上是关于单例模式详解的主要内容,如果未能解决你的问题,请参考以下文章

Java 单例模式详解

三单例模式详解

单例模式(单例设计模式)详解

单例模式详解

单例模式详解

单例模式详解