单例模式(Singleton Pattern)
单例(Singleton)模式的定义:
指确保一个类只有一个实例,并提供一个唯一的全局访问点。
单例模式下,构造函数是私有属性,注意:构造函数本身应该就是静态的(我猜的),现在只是把访问的权限也设置为私有的了,所以外部就无法直接new实例了。只能通过本类的其他静态方法去调用构造方法,也就是new实例。
单例模式的实现主要有两种:
第 1 种:懒汉式单例:
该模式的特点是类加载时没有生成单例,只有当第一次调用 getlnstance 方法时才去创建这个单例。单线程
package s_concreteClass;
/**
*
* 凡是单例,都要将构造方法声明为私有方法,外部无法通过类名访问。所以外部无法创建实例。
* 经典单例模式,单线程中使用,不考虑多线程
* 也叫懒汉式单例.
* @author mathew
*
*/
public class TypicalSingleton {
private static TypicalSingleton uniqueInstance;
//将构造方法声明为私有方法,外表无法通过类名访问。所以外部无法创建实例。
private TypicalSingleton () {
System.out.println("这是懒汉式单例,典型单例TypicalSingleton !!!");
}
public static TypicalSingleton getInstance() {
if (uniqueInstance == null ) {
uniqueInstance = new TypicalSingleton();
}
return uniqueInstance;
}
public void getName(){
System.out.println("这是TypicalSingleton的getName!!");
}
}
同步块的懒汉单例:
package s_concreteClass;
/**
* 使用同步关键字解决多线程中的单例冲突问题,但是每次访问的时候都要先访问同步块,降低性能
* @author mathew
*
*/
public class SyncSingleton {
private static SyncSingleton uniqueInstance;
private SyncSingleton () {
System.out.println("这是单同步单例,SyncSingleton !!!");
}
//在公共的访问方法中加synchronized关键字,外部访问都需要经过同步块,影响性能
public static synchronized SyncSingleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new SyncSingleton();
}
return uniqueInstance;
}
public void getName() {
System.out.println("这是SyncSingleton的getName!!");
}
}
双重锁的懒汉单例(double check):
package s_concreteClass;
/**
* 双重检查加锁单例,需要用到volatile关键字,保证每次访问的单例都是内存上的,而不是缓存区的。所以值是最新的。
* 在全局访问方法里面的判断条件里加同步关键字,而不是在方法声明的时候就加,避免了每次访问都要经过同步块,提升性能。
* 其实还是饿汉式单例好用
* @author mathew
*
*/
public class DoubleCheckSingleton {
//需要用到volatile关键字,保证每次访问的单例都是内存上的,而不是缓存区的。所以值是最新的。
private static volatile DoubleCheckSingleton uniqueStance;
private DoubleCheckSingleton() {
System.out.println("这是双重检查加锁(double check )单例,DoubleCheckSingleton !!!");
}
public static DoubleCheckSingleton getInstance() {
if(uniqueStance == null) {
synchronized (DoubleCheckSingleton.class) {
//双重检查,避免在进入代码块之前的一瞬间被其他线程抢先创建了实例,避免了重复创建,保证了唯一性
if (uniqueStance == null) {
uniqueStance = new DoubleCheckSingleton();
}
}
}
return uniqueStance;
}
public void getName() {
System.out.println( "这是DoubleCheckSingleton的getName!!");
}
}
第 2 种:饿汉式单例:
该模式的特点是类一旦加载就创建一个单例,保证在调用 getInstance 方法之前单例已经存在了。
package s_concreteClass;
/**
* 饿汉式单例,也叫急切时单例,在声明变量时候就创建实例,完美解决多线程问题,而且不会多次访问同步块
* @author mathew
*
*/
public class EagerlySingleton {
//在声明变量的时候就创建实例
private static EagerlySingleton uniqueInstance = new EagerlySingleton();
private EagerlySingleton() {
System.out.println("这是饿汉式(eagerly check )单例,EagerlySingleton !!!");
}
public static EagerlySingleton getInstance() {
return uniqueInstance;
}
public void getName() {
System.out.println("这是EagerlySingleton的getName!!");
}
}