设计模式:单例模式Singleton

单例模式

保证一个类只有一个实例,并且提供一个访问他的全局访问点 --《设计模式:可复用面向对象软件的基础》84页3.5节

在某些情况下我们需要一个类在任何情况下 只需要同一个实例并且提供一个访问该实例的方法

单例模式又分懒汉和饿汉模式

懒汉模式:在你需要他的时候才会去创建对象,也就是你在调用访问该实例的方法的时候才会去创建

/**
* 单例模式 :懒汉模式
*
* @author 爱出走的眼睛
*
*/
public class Singleton {
private static Singleton singleton;

private Singleton() {
System.out.println("创建对象");
}

public static Singleton GetInstance() {
if (singleton==null) {
singleton=new Singleton();
}
return singleton;

}
}

//测试代码
Singleton s1 = Singleton.GetInstance();
Singleton s2 = Singleton.GetInstance();
System.out.println(s1==s2);

//结果为 true

上述代码并非严格,因为没有考虑到多线程的环境下 下面我测试一下在多线程情况下出现的问题

public class Test {
public static void main(String[] args) {

Thread tA = new Thread() {
public void run() {
Singleton.GetInstance();
}
};

Thread tB = new Thread() {
public void run() {
Singleton.GetInstance();
}
};
tA.start();
tB.start();
}
}

打印结果为:

创建对象

创建对象

因为在多线程的情况下 线程A可能在创建对象之前cpu时间片用完了进入就绪状态,线程B分配到资源 这个时候由于线程A没有执行完创建对象语句,此时线程B判断依然对象为空,所以线程B也会去创建对象,这样两个线程都进入了if里面 导致单例模式失败!

严格的单例模式 懒汉

/**
* 单例模式 :严格的懒汉模式
*
* @author 爱出走的眼睛
*
*/
public class Singleton {
//使用volatile 关键字 禁止指令排序
private static volatile Singleton singleton;

private Singleton() {

}

public static Singleton GetInstance() {
//这里 锁代码块比锁方法更加高效
if (singleton==null) {
synchronized(Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}

}
return singleton;
}
}
如果不懂volatile 和线程的话 需要自己补习一下同步锁和volatile 关键字
饿汉模式: 不管你调用不调用 它都会去创建这个对象
饿汉代码就简单很多
public class SingletonHungry {
//注意这里使用了final关键字
private static final SingletonHungry singleton=new SingletonHungry();

private SingletonHungry() {

}

public static SingletonHungry GetInstance() {

return singleton;

}
}

应用场景

最简单的一个小例子 windows系统中的任务管理器 无论你打开多少次任务管理器 他只会有一个窗口

因为如果你打开两个任务管理器窗口 且内容一样 管理器需要去调用CPU去获取这些信息 这样设计的目的是为了减少资源浪费 所以设计成单例模式,第二点 如果你打开两个管理器发现内容不一样 这样更容易给用户带来误解。

spring中的bean默认就是单例模式

线程池,数据库连接池,日志对象这些也用到了单例模式

原文:https://blog.csdn.net/ly610501737/article/details/93097078

发表评论
留言与评论(共有 0 条评论)
   
验证码:

相关文章

推荐文章

'); })();