1什么是单例设计模式:
所谓类得单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法;
2.单例模式有两种方式:
2.1饿汉式
如何实现:
①构造器私有化=>防止用户直接去new。
②类得内部创建对象
③向外暴露一个静态的公共方法,getInstance
④代码实现
public class Singleton {
// 在类加载时就创建实例
//为了在静态方法中使用,需要将其修饰为static;
private static Singleton instance = new Singleton();
// 私有构造方法,防止外部类直接实例化
private Singleton() {
}
// 静态方法返回实例
public static Singleton getInstance() {
return instance;
}
}
在这个例子中,Singleton
类的构造方法被声明为私有,外部类无法直接实例化该类。在类加载时,静态变量instance
被初始化为一个Singleton
的实例,因此在整个程序运行期间,只会创建一个Singleton
对象。
通过getInstance()
方法,可以获取到该实例。由于在类加载时就已经创建了实例,因此无需考虑线程安全问题。
使用饿汉式实现的单例模式具有以下特点:
-
线程安全:由于在类加载时就创建了实例,因此不存在多线程并发访问的问题。
-
简单直接:实现简单,无需考虑线程同步和延迟初始化的问题。
-
可能造成资源浪费:由于在类加载时就创建了实例,如果该实例在程序运行期间很少被使用,可能会造成资源的浪费。
需要注意的是,饿汉式的单例模式适用于单线程环境或者对资源使用效率要求较高的情况。在多线程环境下,如果多个线程同时调用getInstance()
方法,可能会导致实例被创建多次,因此需要考虑线程安全问题。
2.2懒汉式
实现步骤:
①构造器私有化;
②定义一个静态属性对象;
③提供一个public的static方法,可以返回一个Cat对象;
public class Singleton {
// 延迟初始化,使用volatile关键字保证可见性
private static volatile Singleton instance;
// 私有构造方法,防止外部类直接实例化
private Singleton() {
}
// 静态方法返回实例
public static Singleton getInstance() {
// 双重检查锁定,确保只有第一次调用时才会创建实例
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
在这个例子中,Singleton
类的构造方法被声明为私有,外部类无法直接实例化该类。在第一次调用getInstance()
方法时,会进行双重检查锁定,确保只有第一次调用时才会创建实例。使用volatile
关键字修饰instance
变量,保证在多线程环境下的可见性。
懒汉式的单例模式具有以下特点:
-
延迟初始化:只有在第一次调用
getInstance()
方法时才会创建实例,可以节省资源。 -
线程安全:通过双重检查锁定,确保在多线程环境下只会创建一个实例。
-
复杂性较高:相比饿汉式,懒汉式的实现较为复杂,需要考虑线程同步和延迟初始化的问题。
需要注意的是,懒汉式的单例模式在多线程环境下需要考虑线程安全问题。通过双重检查锁定可以解决线程安全问题,但在某些情况下可能会出现双重检查锁定失效的问题,因此需要谨慎使用。
3.两者的区别:
①两者最主要的区别,在于创建对象的时机不同:饿汉式是在类加载就创建了对象实例,而懒汉式是在使用时才创建;
②饿汉式不存在线程安全问题,而懒汉式存在;
③饿汉式存在资源浪费的问题,如果一个程序员一个对象实例都没有使用,那么饿汉式创建的对象就浪费了,而懒汉式不存在;
④javase标准类中,java.lang.Runtime就是经典的单例模式;