详细内容及例子:http://blog.csdn.net/jason0539/article/details/23297037/
单例模式有以下特点:1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
举例:
懒汉式单例类://懒汉式单例类.在第一次调用的时候实例化自己
public class Singleton { private Singleton() {} private static Singleton single=null; //静态工厂方法 public static Singleton getInstance() { if (single == null) { single = new Singleton(); } return single; } }
<1>将构造方法限定为private避免了类在外部被实例化
<2>在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。
实际上:通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。(单例模式被java反射机制攻击)
缺点:没有考虑到线程安全,所以我们对getInstance()方法进行改造----------->
懒汉式单例类:
(加同步锁)
public static synchronized Singleton getInstance() { if (single == null) { single = new Singleton(); } return single; }
(加双重校验锁的懒汉式)
public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton == null) { singleton = new Singleton(); } } } return singleton; }
(静态内部类)既实现了线程安全,又避免了同步带来的性能影响。
public class Singleton { private static class LazyHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton (){} public static final Singleton getInstance() { return LazyHolder.INSTANCE; } }
二、饿汉式单例//饿汉式单例类.在类初始化时,已经自行实例化
public class Singleton1 { private Singleton1() {} private static final Singleton1 single = new Singleton1(); //静态工厂方法 public static Singleton1 getInstance() { return single; } }
饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。
三、登记式单例(可忽略)
//类似Spring里面的方法,将类名注册,下次从里面直接获取。 public class Singleton3 { private static Map<String,Singleton3> map = new HashMap<String,Singleton3>(); static{ Singleton3 single = new Singleton3(); map.put(single.getClass().getName(), single); } //保护的默认构造子 protected Singleton3(){} //静态工厂方法,返还此类惟一的实例 public static Singleton3 getInstance(String name) { if(name == null) { name = Singleton3.class.getName(); System.out.println("name == null"+"--->name="+name); } if(map.get(name) == null) { try { map.put(name, (Singleton3) Class.forName(name).newInstance()); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (ClassNotFoundException e) { e.printStackTrace(); } } return map.get(name); } //一个示意性的商业方法 public String about() { return "Hello, I am RegSingleton."; } public static void main(String[] args) { Singleton3 single3 = Singleton3.getInstance(null); System.out.println(single3.about()); } }
登记式单例实际上维护了一组单例类的实例,将这些实例存放在一个Map(登记薄)中,对于已经登记过的实例,则从Map直接返回,对于没有登记的,则先登记,然后返回。
这里我对登记式单例标记了可忽略,我的理解来说,首先它用的比较少,另外其实内部实现还是用的饿汉式单例,因为其中的static方法块,它的单例在类被装载的时候就被实例化了。
饿汉式和懒汉式区别:
饿汉就是类一旦加载,就把单例初始化完成,保证getInstance的时候,单例是已经存在的了,
而懒汉比较懒,只有当调用getInstance的时候,才回去初始化这个单例。
1、线程安全:
饿汉式天生就是线程安全的,可以直接用于多线程而不会出现问题,
懒汉式本身是非线程安全的,为了实现线程安全有几种写法,分别是上面的1、2、3,这三种实现在资源加载和性能方面有些区别。
2、资源加载和性能:饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,都会占据一定的内存,但是相应的,在第一次调用时速度也会更快,因为其资源已经初始化完成。
而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次调用时要做初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。
至于1、2、3这三种实现又有些区别,
第1种,在方法调用上加了同步,虽然线程安全了,但是每次都要同步,会影响性能,毕竟99%的情况下是不需要同步的,
第2种,在getInstance中做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗
第3种,利用了classloader的机制来保证初始化instance时只有一个线程,所以也是线程安全的,同时没有性能损耗,所以一般我倾向于使用这一种。
什么是线程安全?
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
或者说:一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题,那就是线程安全的。
单例模式为一个面向对象的应用程序提供了对象惟一的访问点,不管它实现何种功能,整个应用程序都会同享一个实例对象。
相关推荐
最新全套Java学习资料打包 最新全套Java学习资料打包 最新全套Java学习资料打包 最新全套Java学习资料打包 最新全套Java学习资料打包 最新全套Java学习资料打包 最新全套Java学习资料打包 最新全套Java...
Java学习路线(鱼皮) Java学习路线(鱼皮)是一条龙版本的学习路线,从入门到入土,旨在帮助学习者快速掌握Java开发的所有知识点。本路线的特点是新、完整、实用、开源、回馈社区、持续更新。 学习路线的主要...
最全JAVA学习路线一条龙思维导图(附资源链接)PS:程序员鱼皮 1. 最新,完整一条龙的大厂 Java 学习路线,从入门到入土 2. 同时适用于想全面学习 / 快速求职的同学,可以根据符号来定制自己的专属学习路线 3. 给出...
java学习java学习java学习java学习java学习java学习
### Java学习入门资料知识点梳理 #### 一、Java语言历史与发展 - **起源与早期发展** - **前身**:Oak(1990年),由James Gosling等人在Sun Microsystems开发。 - **Green项目**:Sun Microsystems于1990年开始...
《Java学习指南(第4版)(上、下册)》是畅销Java学习指南的ZUI新版,详细介绍了Java 6和Java 7的语言特性和API。本书全面介绍了Java的基础知识,力图通过完备地介绍Java语言、其类库、编程技术以及术语,从而成为一本...
java学习心得java学习心得java学习心得java学习心得
《Java入门1·2·3:一个老鸟的Java学习心得》是一本与众不同的Java入门好书。作者以独特的视角,向Java初学者讲述了如何才能真正理解和掌握Java语言。《Java入门1·2·3:一个老鸟的Java学习心得》充分考虑了初学Java...
java学习java学习
总之,“Java学习资料大全”应该包含了以上各个领域的教程、示例代码、实践项目和相关书籍,为初学者到高级开发者提供了全面的学习资源。通过深入学习并不断实践,可以成为一名熟练的Java开发者。
java学习方法及学习总结 java学习方法及学习总结 java学习方法及学习总结
java 学习路线图-2018最新 以有趣和好理解的方式展示Java和Web的内容 设计一些略有挑战的练习 创造一些便于理解和消化知识点的方式,享受这个创造的过程
java 学习推荐书籍
JAVA学习资料大全JAVA学习资料大全JAVA学习资料大全
【JAVA编程学习】是计算机科学领域的一个重要主题,尤其对于初学者来说,它是一个非常有价值的起点。Java是一种广泛使用的面向对象的编程语言,以其“一次编写,到处运行”的特性而闻名,这得益于Java虚拟机(JVM)...
标题《30套最实用JAVA学习视频教程合集》所涉及的知识点主要围绕Java学习资源的汇总。Java作为一门广泛使用的编程语言,在互联网和企业级应用中扮演着重要角色。为了帮助初学者或者已经从事Java开发的程序员快速掌握...
B站韩顺平老师Java学习路线
而今天,我们要介绍的这份《良葛格JAVA学习笔记》便是一份得到广泛好评,深受学习者喜爱的学习资源。 首先,我们不得不提的是这份笔记的作者——“良葛格”,一个在编程教育界颇具声望的人物。他的这份学习笔记因...
《JAVA学习从150道经典例题突破》这份资源,正是为了满足广大编程初学者这一需求而精心制作的。 本书的编排结构从基础概念入手,逐步向更深层次的内容推进,每一章都围绕着特定的编程主题展开,通过实例帮助学习者...