- 概念: 单例模式在23种设计模式中属于创建型模式,是常见的设计模式之一。
- 案例:
这里以经典的数据库驱动连接工具类为例;
数据库连接工具类在各个业务的dao层会被初始化调用;
而每一次初始化都会在堆内存中申请一片空间,这是对堆内存资源的浪费;
如果在堆内存只开辟一片空间,各个业务的Dao层建立不同的引用进行操作,就可以资源利用最大化; 单例设计模式就应运而生,它就是为了解决对象初始化,造成资源浪费的情况;
- 术语 单例:Singleton
- 三要素:
-
私有的构造方法;
-
指向自己实例的私有静态引用;
-
以自己实例为返回值的静态的公有方法。
-
- 分类
1.饿汉式(静态常量)
public class DBAccess {
// 构造器私有化,避免外部创建对象
private DBAccess() {
}
// static修饰,保障其能够被静态方法访问
private final static DBAccess dbAccess = new DBAccess();
// 外部直接调用静态方法实例化对象
public static DBAccess getInstance() {
return dbAccess;
}
}
2.饿汉式(静态代码块)
class DBAccess2 {
private DBAccess2() {
}
private static DBAccess2 dbAccess = null;
static {
dbAccess = new DBAccess2();
}
public static DBAccess2 getInstance() {
return dbAccess;
}
}
3.懒汉式(线程不安全)
class DBAccess3 {
private DBAccess3() {
}
private static DBAccess3 dbAccess = null;
public static DBAccess3 getInstance() {
if (dbAccess == null) {
dbAccess = new DBAccess3();
}
return dbAccess;
}
}
4.懒汉式(线程安全,同步代码块)
class DBAccess4 {
private DBAccess4() {
}
private static DBAccess4 dbAccess = null;
public static DBAccess4 getInstance() {
synchronized (DBAccess4.class) {
if (dbAccess == null) {
dbAccess = new DBAccess4();
}
}
return dbAccess;
}
}
5.懒汉式(线程安全,同步方法)
class DBAccess5 {
private DBAccess5() {
}
private static DBAccess5 dbAccess = null;
public synchronized static DBAccess5 getInstance() {
if (dbAccess == null) {
dbAccess = new DBAccess5();
}
return dbAccess;
}
}
6.双重检查
class DBAccess6 {
private DBAccess6() {
}
private static DBAccess6 dbAccess = null;
public static DBAccess6 getInstance() {
if (dbAccess == null) {
synchronized (DBAccess6.class) {
if (dbAccess == null) {
dbAccess = new DBAccess6();
}
}
}
return dbAccess;
// return new DBAccess6();
}
}
7.静态内部类
class DBAccess7 {
private DBAccess7() {
}
private static class DBAccess7Instance {
private static DBAccess7 dbAccess = new DBAccess7();
}
public static DBAccess7 getInstance() {
return DBAccess7Instance.dbAccess;
}
}
8.枚举
enum DBAccess8 {
DBACCESS;
public static DBAccess8 getInstance() {
return DBAccess8.DBACCESS;
}
}
- 饿汉式和懒汉式的区别
(1)饿汉式和懒汉式的主要区别是他们使用的加载策略不同,饿汉式使用的是立即加载,而懒汉式用的是延迟加载(懒加载)。简单来说就是饿汉式不管你用不用,它都实例了。而懒汉式是当你调用方法时它才去实例。
(2)饿汉式虽存在性能问题,但它是线程安全的,而懒汉式可能存在线程不安全的问题,当然也可以通过同步代码块或同步方法的方式解决,如上面4、5。(注:4比5的性能更好)。
- 结论:
单例中两种饿汉式可用,但是存在性能问题
单例中三种懒汉式不推荐,存在线程安全问题,同步方法的方式解决了线程的问题,但是性能极差
最后三种单例模式值得推荐
- 注意事项
-
系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能
-
当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用 new
-
- 应用
- jdk源码中Runtime类
- tomcat中ApplicationContext类
- session 工厂
学习记录,若有错误,欢迎指正,若有疑问,欢迎评论。
求点赞
作者:借我丹青妙笔



