Java设计模式(一)之单例模式

一、什么是单例模式?

单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

二、单例模式特点:

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

三、单例模式作用:

1.控制资源的使用,通过线程同步来控制资源的并发访问;
2.控制实例产生的数量,达到节约资源的目的。
3.作为通信媒介使用,也就是数据共享,它可以在不建立直接关联的条件下,让多个不 相关的两个线程或者进程之间实现通信。

四、单例模式的实现

1、懒汉模式

public class SingletonDemo {
    
    
    private static SingletonDemo instance;
    private SingletonDemo(){
    
    
 
    }
public static SingletonDemo getInstance(){
    
    
		//此处判断
        if(instance==null){
    
    
            instance=new SingletonDemo();
        }
        return instance;
    }
}

先声明instance对象,然后访问者访问的时构造对象。若多个访问者同时访问getInstance(),在上方注释处,此时大家都为null,故都会构造对象。所以懒汉模式线程不安全。那么懒汉式如何转变为线程安全呢?懒汉式的第二种变式getInstance()加锁

public class SingletonDemo {
    
    
    private static SingletonDemo instance;
    private SingletonDemo(){
    
    
 
}
	//此处加锁
    public static synchronized SingletonDemo getInstance(){
    
    
        if(instance==null){
    
    
            instance=new SingletonDemo();
        }
        return instance;
    }
}

当访问者访问getInstance方法的时候,上锁不给其他人访问。故此方法线程安全。但大多数情况都是非并发情况,此时加锁则浪费资源。这种实现效率极低。于是有了懒汉式的三种变式Double CheckLock实现单例

public class SingletonDemo {
    
    
    private static SingletonDemo instance;
    private SingletonDemo(){
    
    
           }
    public static SingletonDemo getInstance(){
    
    
        if(instance==null){
    
    
			//多个访问者在此等待
            synchronized (SingletonDemo.class){
    
    
                if(instance==null){
    
    
                    instance=new SingletonDemo();
                }
            }
        }
        return instance;
    }
}

在调用getInstance方法时,进行两次判空。原因是:多个进程同时调用getInstance,此时instance没有被实例化,都会进入if,线程A进去加锁,线程BCD在等待,线程A实例化之后,释放锁,BCD分别进入锁内因为此时Instance已经存在,所以不会继续实例化,return null。所以这种方法只实例化了一次instance。线程是安全的。

2、饿汉模式

public class SingletonDemo {
    
    
    private static SingletonDemo instance=new SingletonDemo();
    private SingletonDemo(){
    
    
 
    }
    public static SingletonDemo getInstance(){
    
    
        return instance;
    }
}

直接创建一个静态对象,以后不再改变,访问者访问的都是同一对象,因此饿汉是线程安全的。

3、静态内部类

public class SingletonDemo {
    
    
//静态内部类  
  private static class SingletonHolder{
    
    
        private static SingletonDemo instance=new SingletonDemo();
    }
    private SingletonDemo(){
    
    
           }
    public static SingletonDemo getInstance(){
    
    
        return SingletonHolder.instance;
    }
}

使用内部类的好处是,静态内部类不会在单例加载时就加载,而是在调用getInstance()方法时才进行加载,达到了类似懒汉模式的效果,而这种方法又是线程安全的。

参考:https://blog.csdn.net/jason0539/article/details/23297037
https://blog.csdn.net/qq_35860138/article/details/86477538

猜你喜欢

转载自blog.csdn.net/xmt1369758466/article/details/106688694