单例模式
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
1、单例类只能有一个实例。
2、单例类必须自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
懒汉模式(线程不安全方式 不推荐 新手一般会这么写)
/**
* 懒汉模式
* 单例实例在第一次使用时被创建 容易出bug 线程不安全的
*/
public class SingletonExample {
//私有构造对象
private SingletonExample(){
}
//单例对象
private static SingletonExample instance = null;
//静态工厂方法
public static SingletonExample getInstance(){
if(instance == null){
instance = new SingletonExample();
}
//这种方法 == null 在单线程下没什么问题,多线程下容易出现问题,因为可能同时有两个以上的线程走到if里
return instance;
}
}
懒汉模式(线程安全方式,加synchronized 不推荐)
/**
* 懒汉模式
* 单例实例在第一次使用时被创建 加了synchronized有开销
*/
@ThreadSafe
public class SingletonExample3 {
//私有构造对象
private SingletonExample3(){
}
//单例对象
private static SingletonExample3 instance = null;
//静态工厂方法 有性能开销
public static synchronized SingletonExample3 getInstance(){
if(instance == null){
instance = new SingletonExample3();
}
return instance;
}
}
懒汉模式(双重检测,但是仍然线程不安全原因是多线程下指令重排!!)
/**
* 懒汉模式 -》 双重同步锁单例模式
* 单例实例在第一次使用时被创建
*/
public class SingletonExample4 {
//私有构造对象
private SingletonExample4(){
}
//1。memory = allocate() 分配对象内存空间
//2。ctoInstance() 初始化对象
//3。instance = memory 设置instance指向刚分配的内存
//JVM和cpu优化 多线程下发生了指令重排
//1。memory = allocate() 分配对象内存空间
//3。instance = memory 设置instance指向刚分配的内存
//2。ctoInstance() 初始化对象
// 双重检测机制出现问题
//单例对象
private static SingletonExample4 instance = null;
//静态工厂方法 有性能开销
public static SingletonExample4 getInstance(){
if(instance == null){//双重检测机制 //B
synchronized(SingletonExample.class) {//同步锁
if (instance == null){
instance = new SingletonExample4(); // A线程执行到这时,完成了 指令的 1 ,3 还没进行初始化。这是B那个位置发现已经不为null了直接就返回回去了。但是 真实的时instance还没初始化完。
}
}
}
return instance;
}
}
懒汉模式(双重检测,加volatile 禁止指令重排, 推荐 )
/**
* 懒汉模式 -》 双重同步锁单例模式
* 单例实例在第一次使用时被创建
*/
public class SingletonExample5 {
//私有构造对象
private SingletonExample5(){
}
//1。memory = allocate() 分配对象内存空间
//2。ctoInstance() 初始化对象
//3。instance = memory 设置instance指向刚分配的内存
//限制发生指令重排
//单例对象 volatile 加上双重检测机制来禁止 指令重排
private volatile static SingletonExample5 instance = null;
//静态工厂方法 有性能开销
public static SingletonExample5 getInstance(){
if(instance == null){//双重检测机制 //B
synchronized(SingletonExample.class) {//同步锁
if (instance == null){
instance = new SingletonExample5(); // A
}
}
}
return instance;
}
}
饿汉模式(推荐)
/**
* 饿汉模式
* 单例实例类装载时进行创建 不足当单例模式过多时,可能会影响性能问题,如果最终没调用,会造成资源浪费。 线程安全的
*/
public class SingletonExample2 {
//私有构造对象
private SingletonExample2(){
}
//单例对象
private static SingletonExample2 instance = new SingletonExample2();
//静态工厂方法
public static SingletonExample2 getInstance(){
return instance;
}
}
饿汉模式(推荐)
/**
* 饿汉模式
* 单例实例类装载时进行创建
*/
public class SingletonExample6 {
//私有构造对象
private SingletonExample6(){
}
//单例对象
private static SingletonExample6 instance = null;
static {
instance = new SingletonExample6();
}
//静态工厂方法
public static SingletonExample6 getInstance(){
return instance;
}
public static void main(String[] args) {
System.out.println(getInstance());
System.out.println(getInstance());
}
}
枚举(最安全 最推荐)
/**
* 枚举模式 最安全
*/
public class SingletonExample7 {
private SingletonExample7(){
}
public static SingletonExample7 getInstance(){
return Singleton.INSTANCE.getInstance();
}
//私有枚举类
private enum Singleton{
INSTANCE;
private SingletonExample7 singleton;
//JVM 保证这个方法绝对只调用一次
Singleton(){
singleton = new SingletonExample7();
}
public SingletonExample7 getInstance(){
return singleton;
}
}
}