学习JAVA.day12 设计模式(单例模式)
因为在设计或开发中,肯定会有这么一种情况,一个类只能有一个对象被创建,如果有多个对象的话,可能会导致状态的混乱和不一致。这种情况下,单例模式是最恰当的解决办法。它有很多种实现方式,各自的特性不相同,使用的情形也不相同。今天要实现的是常用的三种,分别是饿汉式、懒汉式和多线程式。
单例的四大原则:
- 构造私有。
- 以静态方法或者枚举返回实例。
- 确保实例只有一个,尤其是多线程环境。
- 确保反序列换时不会重新构建对象。
通过单例模式,可以做到:
- 单例类只能有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。
1). 饿汉式
饿汉单例,即在最开始的时候,静态对象就已经创建完成;
设计方法是类中包含一个静态成员指针,该指针指向该类的一个对象,提供一个公有的静态成员方法,返回该对象指针;为了使得对象唯一,还需要将构造函数设为私有;
代码实现:
package cn.itcast.day23;
public class Single { //饿汉式
private Single() {}
private static final Single singleNode = new Single();
//静态工厂方法:
//静态工厂方法指的是在类中提供一个公有的静态方法,返回类的一个实例。
public static Single getInstance() {
return singleNode;
}
}
线程安全问题:单例的饿汉实现是线程安全的,因为对象在使用前就已经创建出来了。
2). 懒汉式
所谓懒汉模式,就是尽可能晚的创建这个对象的实例,即在单例类第一次被引用时将自己初始化;其实JAVA里很多地方都是类似这样的思想,目的是尽量使资源的利用最大化,不要让空闲的人还占着有限的资源。
代码实现:
package cn.itcast.day23;
public class Single{ //懒汉式
private Single() {}
private static Single singleNode = null;
public static Single getInstance() {
if (singleNode == null) {
singleNode = new Single();
}
return singleNode;
}
}
线程安全问题:如果此时多线程进行操作,简单点以两个线程为例,假设pthread_1刚判断完 singleNode 为null为真,准备创建实例的时候,切换到了pthread_2, 此时pthread_2也判断singleNode 为null为真,创建了一个实例,再切回pthread_1的时候继续创建一个实例返回,那么此时就不再满足单例模式的要求了。
解决方法:
(1). 在getInstance方法上加同步
package cn.itcast.day23;
public class Single{ //懒汉加同步
private Single() {}
private static Single singleNode = null;
public static synchronized Single getInstance() {
if (singleNode == null) {
singleNode = new Single();
}
return singleNode;
}
}
(2). 双重检查锁定
package cn.itcast.day23;
public class Single{ //懒汉加同步
private Single() {}
private static Single singleNode = null;
public static Single getInstance() {
if (singleNode == null) {
synchronized (Single.class) {
if (singleNode == null) {
singleNode = new Single();
}
}
}
return singleNode;
}
}
有关“双重检查锁定失效”的说明: http://ifeve.com/doublecheckedlocking/
(3). 静态内部类
package cn.itcast.day23;
public class Single {
private static class Inner {
private static final Single singleNode = new Single();
}
private Single (){}
public static final Single getInstance() {
return Inner.singleNode;
}
}
深入理解单例模式:静态内部类单例原理: https://blog.csdn.net/mnb65482/article/details/80458571
别问,问就是不会,需要继续深造;