1.Define Singleton(单例的定义)
数学与逻辑学中,singleton定义为“有且仅有一个元素的集合”。
通俗的讲:一个类有且仅有一个实例,并且自行实例化向整个系统提供。显然单例模式的要点有三个;一是某个类只能有一个实例;二是它必须自行创建这个实例;三是它必须自行向整个系统提供这个实例.
单例原则:无状态的对象,可以统统做成单例的,(无状态表示没有数据属性)比如:Service类只有方法没有属性时,可以做成单例。Service和Dao在Spring中可以做成单例的,只读的类可以做成单例的。当然是可以把一个无状态的变成单例。单例分为传统上的单例和管理层次上的单例。
2. 实现单例的三要素:
1>. 单例模式的类只提供私有的构造函数;
2>. 类定义中含有一个该类的静态私有对象;
3>. 该类提供了一个静态的共有的函数用于创建或获取它本身的静态私有对象。
Java单例模式典型传统的简单例子:(这种写法线程不安全,多线程不能正常工作)
package com.demo.singleton;
public class Singleton {
//1.静态私有对象
private static Singleton singleton = null;
//2.静态私有构造方法方法
private Singleton() {
}
//3.静态的共有的函数用于创建或获取它本身的静态私有对象
public static Singleton getInstant() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
3.单例模式的3中形式
1>.懒汉式,也是常用的形式。加synchronized为线程安全的,这种写法能够在多线程中很好的工作,而且看起来它也具备很好的lazy loading,但是,遗憾的是,效率很低,99%情况下不需要同步。
public class Singleton {
//1.静态私有对象
private static Singleton singleton = null;
//2.静态私有构造方法方法
private Singleton() {
}
//3.静态的共有的函数用于创建或获取它本身的静态私有对象
public static synchronized Singleton getInstant() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
2>. 饿汉式,在自己的内部实例化一个对象,只给内部调用。
这种方式基于class loder机制避免了多线程的同步问题,不过,instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用get Instance方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到lazy loading的效果。
public class Singleton {
//1.静态私有对象
//饿汉式:在自己内部定义自己的一个实例,只供内部调用
private static Singleton singleton = new Singleton();
//2.静态私有构造方法方法
private Singleton() {
}
//3.静态的共有的函数用于创建或获取它本身的静态私有对象,饿汉式
public static Singleton getInstant() {
return singleton;
}
}
3. 双重锁的形式,这个模式将同步内容下方到if内部,提高了执行的效率,不必每次获取对象时都进行同步,只有第一次才同步,创建了以后就没必要了。注意:在JDK1.5之后,双重检查锁定才能够正常达到单例效果。
public class Singleton {
//1.静态私有对象
private static Singleton singleton = null;
//2.静态私有构造方法方法
private Singleton() {
}
//3.静态的共有的函数用于创建或获取它本身的静态私有对象,双重锁形式
public static Singleton getInstant() {
if (singleton == null) {
//线程同步,互斥处理
synchronized(Singleton.class){
if(singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}