【设计模式之单例模式】(SINGLETON|JAVA)
【摘要】 前言设计模式:主要关注软件系统的设计的设计,与具体语言无关。单例模式:确保一个类只有一个实例,并且提供了对该类的全局访问入口。单例模式属于创建者模式速记关键字:单实例实现恶汉模式 * 恶汉模式 * 类加载到内存后,就实例化一个单例,JVM保证线程安全, 简单实用,推荐使用。 * 唯一缺点:不管加载到与否,类装载时就完成实例化public class Mgr01 { private st...
前言
设计模式:主要关注软件系统的设计的设计,与具体语言无关。
单例模式:确保一个类只有一个实例,并且提供了对该类的全局访问入口。
单例模式属于创建者模式
速记关键字:单实例
实现
恶汉模式
* 恶汉模式
* 类加载到内存后,就实例化一个单例,JVM保证线程安全, 简单实用,推荐使用。
* 唯一缺点:不管加载到与否,类装载时就完成实例化
public class Mgr01 {
private static final Mgr01 INSTANCE = new Mgr01();
//私有化构造方法别人无法使用
private Mgr01(){};
//对外提供访问方法
public static Mgr01 getInstance(){
return INSTANCE;
}
public static void main(String[] args) {
Mgr01 instance = Mgr01.getInstance();
Mgr01 instance1 = Mgr01.getInstance();
System.out.println(instance == instance1);
}
}
返回结果为True,证明两个对象是同一个对象
//恶汉2,使用静态语句块完成初始化
public class Mgr02 {
private static final Mgr02 INSTANCE ;
static {
INSTANCE = new Mgr02();
}
private Mgr02(){};
public static Mgr02 getInstance(){
return INSTANCE;
}
public static void main(String[] args) {
Mgr02 instance = Mgr02.getInstance();
Mgr02 instance1 = Mgr02.getInstance();
System.out.println(instance == instance1);
}
}
懒汉模式
* 用到的时候,才给它初始化
* 虽然也达到的初始化的目的,却带来了线程不安全的问题
public class Mgr03 {
private static Mgr03 INSTANCE ;
//私有化构造方法别人无法使用
private Mgr03(){};
//对外提供访问方法
public static Mgr03 getInstance(){
if(INSTANCE==null){
try {
//不让它睡,是看不出效果的
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Mgr03();
}
return INSTANCE;
}
public static void main(String[] args) {
//hash码相同也有可能不是同一个对象,同一个类的不同对象它的hash码是不同的。
for (int i=0; i<100; i++ ){
new Thread(()->{
System.out.println(Mgr03.getInstance().hashCode());
}).start();
}
}
}
运行结果:发现并不是所有的实例都是相同的,证明在多线程条件下是不安全的。
16560739
16560739
15565060
15226649
19687554
245682
懒汉模式之线程安全
* 懒汉模式,加锁,双从判断来解决,线程安全问题,加volatile来保证变量的内存可见性, 禁止指令重排序
public class Mgr04 {
private static volatile Mgr04 INSTANCE ;
//私有化构造方法别人无法使用
private Mgr04(){};
//对外提供访问方法
public static Mgr04 getInstance(){
if(INSTANCE==null){
synchronized (Mgr04.class){
if(INSTANCE == null){
try {
//不让它睡,是看不出效果的
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Mgr04();
}
}
}
return INSTANCE;
}
public static void main(String[] args) {
//hash码相同也有可能不是同一个对象,同一个类的不同对象它的hash码是不同的。
for (int i=0; i<100; i++ ){
new Thread(()->{
System.out.println(Mgr04.getInstance().hashCode());
}).start();
}
}
}
运行结果
29609474
29609474
29609474
29609474
29609474
29609474
29609474
结论
使用懒汉模式,简单又安全。现在也不用写单例了,因为都交给spring了。
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
作者其他文章
评论(0)