单例模式--java代码实现
单例模式
单例模式,顾名思义,在程序运⾏中,实例化某个类时只实例化⼀次,即只有⼀个实例对象存在。例如在古代,⼀个国家只能有⼀个皇帝,在现代则是主席或总统等。
在Java语⾔中单例模式有以下实现⽅式
1.饿汉式
import org.junit.jupiter.api.Test;
public class Singleton {
//静态成员变量
private static Singleton singleton = new Singleton();
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//构造函数私有化
private Singleton(){
}
//返回静态资源中Singleton实例
public static Singleton getInstance() {
return singleton;
}
/**
* 单元测试
*/
@Test
public void testSingleton() {
//通过调⽤类的静态⽅法返回类的实例对象
Singleton s1 = Instance();
Singleton s2 = Instance();
s1.setName("zhangsan");
s2.setName("lisi");
System.out.Name());
System.out.Name());
}
}
在类加载时,直接将实例对象初始化,并且该实例是静态的,属于类的成员变量,通过调⽤类的静态⽅法返回该对象。 单例模式的几种实现方式
运⾏testSingleton单元测试,输出的两⾏都是lisi,因为s1,s2指向的同⼀个实例对象,这个对象在类创建的时候就存在了。
饿汉式是线程安全的,不管系统的那⼀个线程获取这个对象,他们都是该类同⼀个对象。缺点是在程序在⼀开始就创建了该对象,占⽤内存空间。下⾯这种实现⽅式增加判断,在程序调⽤时才实例化该对象。
2.懒汉式
import org.junit.jupiter.api.Test;
public class Singleton {
//不初始化实例对象
private static Singleton singleton = null;
private String name;
public String getName() {
return name;
}
//构造函数私有化
private Singleton(){
}
public void setName(String name) {
this.name = name;
}
//当被调⽤时才动态实例化
public static Singleton getInstance() {
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
懒汉式解决了饿汉式的实例对象初始化占⽤内存的情况,但是懒汉式存在线程安全的问题,当多个线
程同时访问getInstance()⽅法时,有可能在第⼀个线程进⼊if语句是还没new Singleton()时,这时第⼆个线程判断if的时候就会为真,则会创建新的实例,单例模式设计失败。
这时需要在getInstance()⽅法上添加synchronized修饰符,表⽰线程同步,即当⼀个线程访问该⽅法时,其他线程需要等待其释放资源。
public static synchronized Singleton getInstance() {
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
这样解决了懒汉式的线程不安全的问题,但是这样会降低系统的性能,当⼀个线程占⽤了该资源,其他的线程只能等待,系统的性能⼤⼤下降。于是乎第三种实现模式,对懒汉式进⾏了改进。
3.双重检测
public static Singleton getInstance() {
if(singleton == null) {
synchronized (Singleton.class) {
if(singleton==null) {
singleton = new Singleton();
}
}
}
return singleton;
}
双重检测,线程访问时有两次检测。
这⾥将synchronized放到判断语句⾥⾯,这样当第⼀个线程调⽤getInstance()⽅法时,singleton为空,进⼊synchronized代码块,其他的线程即使也判断singleton为空,则需要等待第⼀个线程完成资源的使⽤,这样保证了线程的安全。
当实例化对象完成时,其他的线程调⽤getInstance()⽅法时,直接返回Singleton对象即可,不⽤再等待,这⼀点优化了系统,提⾼了系统的性能。
4.总结
模式来源于⽣活。本⽂⽤Java语⾔实现了单例模式。三种实现⽅式都是线程安全的,饿汉式⽐较占⽤内存空间;懒汉式则降低了系统的性能;双重检测是懒汉式的升级,即能保证线程的安全,也能以懒加载的⽅式实现单例模式,在⼤规模系统中节省对象的创建时间,提⾼系统的性能。在系统中共享同⼀个资源或同⼀个对象,则可利⽤单例模式来实现。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论