定义: 在整个运行过程中,一个类只有一个实例对象
为什么要用?
有些对象创建消耗资源,如果频繁创建和销毁那将会造成性能浪费,所以我们要用单例模式。
常用的一种方法
public class Singleton {
private volatile static Singleton singleton;
private Singleton () {
}
public static Singleton getSingleton() {
if (null == singleton) {
synchronized (Singleton.class) {
if (null == singleton) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
class main {
public static void main(String[] args) {
System.out.println(Singleton.getSingleton());
}
}
主要从1、是否线程安全 2 是否懒加载 3 能否反射破坏(人为)
===========================
下面是其他各类方法
一:只适用单线程环境(不推荐)
/**
* @author kegekeqi
* @version 1.0
* @date 2021-12-7 7:50
*/
public class Javasingleton {
private Javasingleton() {
}
private static Javasingleton instance = null;
public static Javasingleton getInstance() {
if (null == instance) {
instance = new Javasingleton();
}
return instance;
}
}
二、加同步锁前后两次判断实例是否存在,也称为双重检测锁
好处:只有当instance为null时,需要获取同步锁,创建一次实例。当实例被创建,则无需试图加锁。
缺点:用双重if判断,复杂,容易出错。
/**
* @author kegekeqi
* @version 1.0
* @date 2021-12-7 7:50
*/
public class Javasingleton {
private Javasingleton() {
}
private static Javasingleton instance = null;
public static Javasingleton getInstance() {
if (null == instance) {
synchronized (Javasingleton.class) {
if (null == instance) {
instance = new Javasingleton();
}
}
}
return instance;
}
}
可能到这里了,大家会提起经常说到的懒汉式、饿汉式和枚举,不要急一一列举,哪种最好用,好好思考一下。
三、饿汉模式
public class HungryManMode {
private static HungryManMode hungryManMode = new HungryManMode();
private HungryManMode(){};
public static HungryManMode getHungryManMode(){
return hungryManMode;
}
}
饿汉模式在类加载的时候就对实例进行创建,避免了多线程重复创建实例的问题,但是类加载就创建一定程度造成了内存的浪费。
四、懒汉模式
public class LazyManMode {
private static LazyManMode lazyManMode = null;
private LazyManMode(){};
public static synchronized LazyManMode getLazyManMode(){
if(lazyManMode == null){
lazyManMode = new LazyManMode();
}
return lazyManMode;
}
}
懒汉模式中在单例需要的时候才进行创建,为了解决存在的并发问题,使用synchronized关键字 进行约束,也就造成了一定的性能浪费
五、枚举
// Singledto.class
public class Singledto implements Serializable {}
// EnumSingleton.class
public enum EnumSingleton {
;
private Singledto singledto;
private EnumSingleton(){
singledto = new Singledto();
}
public Singledto getSingledto(){
return singledto;
}
}
枚举中的实例被保证只会被实例化一次,所以需要的实例也会保证实例化一次,枚举强烈推荐
六、静态内部类(建议使用)
按需创建实例
由于私有的属性,他人无法使用SingleHolder,不调用SingletonHolder.getInstance()就不会创建实例。
public class JavaSingleton {
private JavaSingleton() {
}
private static class SingletonHolder {
private final static JavaSingleton instance = new JavaSingleton();
}
public static JavaSingleton getInstance() {
return SingletonHolder.instance;
}
}
除此之外,还有利用C#的静态构造函数,确保只创建一个实例。还有利用私有嵌套类型的特性做到真正需要的时候才会创建实例,提高空间使用效率,减少资源的浪费。
补充:比如懒汉式可以人为用反射去破坏,防止这种事情发生可以用枚举类。