• Java设计模式之单例模式


    概述

    设计模式(Design Pattern)是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
    使用设计模式的目的:为了代码可重用性、让代码更容易被他人理解、保证代码可靠性。 设计模式使代码编写真正工程化;设计模式是软件工程的基石脉络,如同大厦的结构一样。
    设计模式可以分为三大类,分别是创建型、结构型和行为型。

    创建型

    单例设计模式

    某个类在被创建的过程中只允许存在一个实例,并且要提供一个访问到它的全局点。
    优点:避免了过多的创建和销毁实例,造成了内存的额外开销;同时可以用在避免资源的多重占用。

    饿汉式单例模式

    public class HunSingleton {
    	private HunSingleton() {}
    	private static HunSingleton singleton = new HunSingleton();
    	
    	public static HunSingleton getSingleton(){
    		return singleton;
    	}
    }
    

    首先,构造器私有保证无法被new出来,其次提前创建好一个对象,通过get方法返回。由于已经直接实例化,因此线程安全。

    懒汉式单例模式(非线程安全)

    public class LazySingleton {
    	
    	private LazySingleton() {}
    	
    	private static LazySingleton lazySingleton;
    	
    	public static LazySingleton getSingleton() {
    		
    		if(lazySingleton == null) { //当两个线程同时走完这步的时候,可能会创建两个对象
    			lazySingleton = new LazySingleton();
    		}
    		
    		return lazySingleton;
    	}
    }
    

    懒汉式相比于饿汉式,优点是可以延迟创建,需要的时候才创建实例对象,不过存在线程安全的问题。

    懒汉式单例模式(线程安全)

    为了解决线程安全问题可以直接加上synchronized关键字,不过锁粒度的增大可能导致性能问题。不推荐使用

    public class LazySingleton {
    	private LazySingleton() {}	
    	private static LazySingleton lazySingleton;
    	
    	public static synchronized LazySingleton getSingleton() {
    		
    		if(lazySingleton == null) {
    			lazySingleton = new LazySingleton();
    		}
    		
    		return lazySingleton;
    	}
    }
    

    双重锁校验(线程安全)

    public class LazySingleton {
    	
    	private LazySingleton() {}
    	
    	private static volatile LazySingleton lazySingleton;
    	
    	public static LazySingleton getSingleton() {
    		
    		if(lazySingleton == null) {
    			synchronized (LazySingleton.class) {
    				if(lazySingleton == null) { 
    					lazySingleton = new LazySingleton();
    				}
    			}
    		}
    		return lazySingleton;
    	}
    }
    

    双重锁校验是基于懒汉式,通过减小锁的粒度来提高性能。第二次判断是预防两个线程a b同时通过了第一个判断,假设a线程获得了锁,创建了对象离开,b线程此时也获得了对象,进行判断,非空直接离开,避免了再次创建。
    同时有一个需要注意的点,比较要有volatile关键字,原因是不加volatile关键字,线程a实例对象的时候可能存在之灵重排,而为完全实例成功的时候,线程b误以为已经实例完成而离开,此时调用将发生错误。关于指令重排可以看volatile相关知识

    静态内部类实现

    public class StaticSingleton {
    	
    	private StaticSingleton() {}
    	
    	private static class SingletonHolder {
            private static final StaticSingleton INSTANCE = new StaticSingleton();
        }
    	
    	public static StaticSingleton getInstance() {
            return SingletonHolder.INSTANCE;
        }
    	
    	
    }
    

    只有当调用getInstance()方法的时候,才会被加载。由于静态类只能被加载一次又保证了线程安全。该方法同时具有延迟加载和通过jvm保证线程安全的机制。

    枚举实现

    以上所有单例模式都无法避免的一个问题是,通过反射,依然可以创建出两个相同的对象。对此,通过枚举来实现单例可以有效的避免这个问题。

    public enum Singleton {
    	INSTANCE;
    }
    
  • 相关阅读:
    [iOS]Xcode+GitHub远程代码托管(GIT, SVN)
    [iOS]Xcode处理过时方法的警告
    [iOS]@synthesize和@dynamic关键字
    [iOS]图片高清度太高, 导致内存过大Crash
    [软件]Xcode查找系统framework所在路径
    [软件]在浏览器里添加MarkDown Here(插件)
    [PHP]利用XAMPP搭建本地服务器, 然后利用iOS客户端上传数据到本地服务器中(四. iOS端代码实现)
    ios -Unity3D的EasyAR集成到已经有项目中。
    iOS创建安全的单例
    阿里云轻量应用服务器 配置mysql详解(转载)
  • 原文地址:https://www.cnblogs.com/helloDuo/p/10303595.html
Copyright © 2020-2023  润新知