所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)
比如 Hibernate 的 SessionFactory,它充当数据存储源的代理,并负责创建 Session 对象。
SessionFactory 并不是轻量级的,一般情况下,一个项目通常只需要一个 SessionFactory 就够,
这是就会使用到单例模式
- 构造器私有化(
防止外部 new)- 类的内部创建对象
- 向外暴露一个静态的公共方法
getInstance
public class Singleton {
//1.私有构造方法
private Singleton() {
}
//2.类的内部创建对象
private static final Singleton instance = new Singleton();
//3.向外暴露一个静态公共方法
public static Singleton getInstance() {
return instance;
}
public static void main(String[] args) {
Singleton singleton = Singleton.getInstance();
Singleton singleton2 = Singleton.getInstance();
System.out.println(singleton.hashCode());
System.out.println(singleton2.hashCode());
}
}
优缺点:
这种单例模式可用,可能造成内存浪费
- 构造器私有化
- 类的内部声明对象
- 在静态代码块中创建对象
- 向外暴露一个静态的公共方法
public class Singleton2 {
//1.构造器私有化
private Singleton2(){};
//2.类的内部声明对象
private static Singleton2 instance;
//3.静态代码块中创建对象
static {
instance = new Singleton2();
}
//4.向外暴露一个静态公共方法
public static Singleton2 getInstance(){
return instance;
}
}
优缺点:
这种单例模式可用,但是可能造成内存浪费
- 构造器私有化
- 类的内部创建对象
- 向外暴露一个静态的公共方法,当使用到该方法时,才去创建 instance
public class Singleton {
//1.构造器私有化
private Singleton() {
}
//2.类的内部创建对象
private static Singleton instance;
//3.向外暴露一个静态的公共方法,当使用到该方法时,才去创建 instance
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
优缺点:
在实际开发中,不要使用这种方式
- 构造器私有化
- 类的内部创建对象
- 向外暴露一个静态的公共方法,加入同步处理的代码,解决线程安全问题
public class Singleton {
//1.构造私有
private Singleton() {
}
//2.类的内部创建对象
private static Singleton instance;
//3.向外暴露一个静态的公共方法,加入同步处理的代码,解决线程安全问题
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
优缺点:
效率太低了,每个线程在想获得类的实例时候,执行getlnstance()方法都要进行同步。而其实这个方法只执行一次实例化代码就够了,后面的想获得该类实例,直接return就行了。方法进行同步效率太低不安全,同步代码块)
- 构造器私有化
- 类的内部创建对象
- 向外暴露一个静态的公共方法,加入同步处理的代码块
public class Singleton {
// 1、构造器私有化
private Singleton() {
}
// 2、类的内部声明对象
private static Singleton instance;
// 3、向外暴露一个静态的公共方法,加入同步处理的代码,解决线程安全问题
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
instance = new Singleton();
}
}
return instance;
}
优缺点:
在实际开发中,不能使用这种方式
- 构造器私有化
- 类的内部创建对象,同时用
volatile关键字修饰修饰- 向外暴露一个静态的公共方法,加入同步处理的代码块,并进行
双重判断,解决线程安全问题
/**
* 双重检查
*/
public class Singleton {
// 1、构造器私有化
private Singleton() {
}
// 2、类的内部声明对象,同时用`volatile`关键字修饰修饰
private static volatile Singleton instance;
// 3、向外暴露一个静态的公共方法,加入同步处理的代码块,并进行双重判断,解决线程安全问题
public static Singleton getInstance() {
if (instance == null) {
synchronized (Singleton.class) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
优缺点:
在实际开发中,推荐使用这种单例设计模式
- 构造器私有化
- 定义一个静态内部类,内部定义当前类的静态属性
- 向外暴露一个静态的公共方法
/**
* 静态内部类
* static保证了变量的初始值,final保证了不被JIT编译器重排序。
* 对于一个单例模式来说,它所在的类在被引用的时候,static会保证它被初始化完毕,
* 且是所有线程所见的初始化,final保证了实例初始化过程的顺寻性。两者结合保证了这个实例创建的唯一性
*/
public class Singleton {
// 1、构造器私有化
private Singleton() {
}
// 2、定义一个静态内部类,内部定义当前类的静态属性
private static class SingletonInstance {
private static final Singleton instance = new Singleton();
}
// 3、向外暴露一个静态的公共方法
public static Singleton getInstance() {
return SingletonInstance.instance;
}
}
优缺点:
推荐使用public enum Singleton {
INSTANCE;
public void sayHello() {
System.out.println("Hello World");
}
}
优缺点:
JDK中 java.lang.Runtime 就是经典的单例模式
