单例设计模式
单例模式简单概述
单例模式:
某些场景,某个类只需要一个实例,
但是你定义一个类之后,是给别人使用的,你不能保证其他人只创建一个实例,
所以通过单例模式设计类,就能保证该类在内存中只有一个实例。
常见的单例模式:
饿汉式:Singleton_lhs
懒汉式:Singleton_ehs
两者的共同点:
1.私有构造器,不能通过new关键字实例化
2.都有一个获取该类实例的公共静态方法
两者的不同点:
1.饿汉式在类内部创建类实例时就初始化了
2.懒汉式在类内部创建类实例时还没初始化,
而是在调用返回类实例的静态方法内部才初始化。
饿汉式
饿汉式实现步骤:
饿汉式的意思是:只要我被加载进内存,我就迫不及待地初始化该类唯一实例。
1.私有化构造器,不能通过new关键字创建该类对象。
2.在类内部声明该类唯一实例成员,并初始化。
3.声明一个返回该类唯一实例的公共静态方法。
饿汉式实现代码
class Singleton_ehs{
private static final Singleton_ehs SINGLETON_EHS = new Singleton_ehs();
private Singleton_ehs(){}
public static Singleton_ehs getSingletonEhs(){
return SINGLETON_EHS;
}
}
饿汉式测试代码
Singleton_ehs singleton_ehs1 = Singleton_ehs.getSingletonEhs();
Singleton_ehs singleton_ehs2 = Singleton_ehs.getSingletonEhs();
System.out.println(singleton_ehs1);
System.out.println(singleton_ehs2);
System.out.println(singleton_ehs1==singleton_ehs2);
运行结果
测试代码中,用类名调用静态方法获取该类的两个对象,分别输出各自的地址,
发现是一样的,并比较两个对象在堆内存中的地址,发现也是一样的,
说明了饿汉式实现单例模式成功了。
cn.xxxq.Singleton_ehs@1540e19d
cn.xxxq.Singleton_ehs@1540e19d
true
懒汉式
懒汉式的意思是:我太懒了,就算我被加载进内存了,也只有等你调用了
获取类实例的方法,我才初始化该类唯一的实例。
1.私有构造器,不能通过new关键字创建该类对象。
2.在类内部声明该类唯一的实例,但不初始化。
3.在类内部声明一个公共静态方法,作用是返回该类唯一的实例。
4.懒汉式会产生线程安全问题。
懒汉式线程安全问题
懒汉式是在调用静态方法时才会实例化,所以会产生线程安全问题,下面用代码说明。
class Singleton_lhs {
private static Singleton_lhs SINGLETON_LHS;
private Singleton_lhs() {}
public static Singleton_lhs getSingletonLhs() {
if (SINGLETON_LHS == null) {
SINGLETON_LHS = new Singleton_lhs();
}
return SINGLETON_LHS;
}
}
由于Java的多线程是抢占式调度,导致了线程执行具有不确定性,
又因为线程执行不确定性,从而导致懒汉式会有线程安全问题。
同步方法解决懒汉式线程安全问题
public static synchronized Singleton_lhs getSingletonLhs_SyncMethod(){
if(SINGLETON_LHS==null){
SINGLETON_LHS = new Singleton_lhs();
}
return SINGLETON_LHS;
}
同步代码块解决懒汉式线程安全问题
public static Singleton_lhs getSingletonLhs_Sync(){
if (SINGLETON_LHS == null){
synchronized (Singleton_lhs.class){
if(SINGLETON_LHS==null){
SINGLETON_LHS = new Singleton_lhs();
}
}
}
return SINGLETON_LHS;
}
懒汉式测试代码
Singleton_lhs singletonLhs1 = Singleton_lhs.getSingletonLhs_Sync();
Singleton_lhs singletonLhs2 = Singleton_lhs.getSingletonLhs_Sync();
System.out.println(singletonLhs1);
System.out.println(singletonLhs2);
System.out.println(singletonLhs1==singletonLhs2);
运行结果
运行结果说明了,同步代码块已经解决了线程安全问题。
cn.xxxq.Singleton_lhs@677327b6
cn.xxxq.Singleton_lhs@677327b6
true
单例模式总结
上面内容就是我对单例模式的见解,大家如果有不同的想法思路,可以提出来一起交流。