**单利模式:**确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例,这个类称为单例类,它提供全 局访问的方法。单例模式是一种对象创建型模式。
三个要点:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
使用方法:
在单例类的内部实现只生成一个实例,同时它提供一个静态的getInstance()工厂方法,让客户可以访问它的唯一实例;为了防止在外部对其实例化,将其构造函数设计为私有;在单例类内部定义了一个Singleton类型的静态对象,作为外部共享的唯一实例。
(1)懒汉单利模式:
线程不安全,多线程下会创建两个对象; 在第一个线程进来后,还未将地址值赋值给mySigleTon,第一线程结束,
第二线程仍然可以进来创建了两个对象;
class MySigleTon {
private static MySigleTon sigleTon = null; // 定义一个类的引用,指向null;
private MySigleTon() { // 构造方法
System.out.println("MySigleTon().init");
}
//提供一个全局的访问点
public static MySigleTon getInstance() {
if(sigleTon == null) { // 如果引用为null,说明没有实例对象此时可以去建立一个
sigleTon = new MySigleTon();
}
return sigleTon;
}
}
(2)懒汉单利模式的几种变种以及存在的问题:
class MySigleTon {
private static MySigleTon mySigleTon = null; // 先定义一个引用,
private MySigleTon() {
System.out.println(".000000");
}
// 提供一个全局访问点
public static MySigleTon getInstance() {
**第一种:**
//在多线程下仍需要将竞态条件至少执行两边
/* 第一个线程进入,未将地址值赋给对象引用,
第二个线程已进入if语句,待解锁之后,进入锁依然创建第二个对象;
*/
if (mySigleTon==null) {
synchronized (lock) {
mySigleTon=new MySigleTon(); //创建对象
}
}
**第二种:**
// 在单线程下效率不高,反复进锁出锁(得进锁之后才能知道不能创建新的对象)
synchronized (lock) {
if (mySigleTon==null) {
mySigleTon=new MySigleTon();
}
}
**第三种:**
// 多线程下会创建两个对象;
/*
在第一个线程进来后,还未将地址值赋值给mySigleTon,第一线程结束,第二线程仍然可以进来
创建了两个对象
*/
if (mySigleTon==null) {
mySigleTon=new MySigleTon();
}
return mySigleTon; //返回唯一的一个对象
}
}
(3) 饿汉单利模式:
// 饿汉式单例模式
class MySigleTon2 {
private static MySigleTon2 mySigleTon2 = new MySigleTon2(); // 首先只能初始化一次,创建一个(唯一的)对象 static修饰,
public MySigleTon2() {
System.out.println("0000002");
}
//提供一个全局的访问点
public static MySigleTon2 getInstance() {
return mySigleTon2;
}
}
(4) 静态内部类实现单利模式:
// 因为静态内部类课以定义静态变量和方法
class MySingleTon3{
private MySingleTon3(){
System.out.println("静态内部类的单利模式");
}
// 只有访问静态内部类才会创建对象
private static class SignleTon {
public static MySingleTon3 mySingleTon3=new MySingleTon3();
}
public static MySingleTon3 getMySingleTon3() {
return SignleTon.mySingleTon3;
}
}
(5)双重校验锁
class MySigleTon {
private static MySigleTon mySigleTon = null; // 先定义一个引用,
private static Object lock = new Object(); // lock 锁;创建了一个锁的对象;
private MySigleTon() {
System.out.println(".000000");
}
// 提供一个全局访问点
public static MySigleTon getInstance() {
// 双重锁,可以防止创建两次对象 多线程和单线程下都可用
if (mySigleTon == null) { // 如果为null,则线程进入等待当前锁执行完进入锁
synchronized (lock) { // synchrnized 线程保护关键字
if (mySigleTon==null) { // 第二线程进入,判断是指向null,
mySigleTon = new MySigleTon(); // 》》》竞态条件 创建一个唯一的对象
}
}
}
return mySigleTon;
}
(5)枚举实现单利模式:
public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}