单例模式
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。
注意:
- 单例类只能有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。
优点:
- 在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。
- 避免对资源的多重占用(比如写文件操作)。
缺点:
- 没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。
实现方式 : 通过将构造方法私有化,使得无法通过构造方法创建对象,然后提供一个对外的接口,用来让外界得到类的实例。
懒汉式
优点:
- 第一次调用才初始化,避免内存浪费。
缺点:
- 必须加锁 synchronized 才能保证单例,但加锁会影响效率
实现方式:
java代码:
package com.dyit.singleton;
import java.util.concurrent.locks.ReentrantLock;
/**
* 单例模式 懒汉模式
* @author strve
*
*/
public class Singleton {
private static Singleton instance = null;
//私有化对象
private Singleton() {
}
//对外提供的接口
public static Singleton getSingleton() {
if (instance==null) {
instance = new Singleton();
}
return instance;
}
}
第一个是线程不安全的,在判断实例是否为空时,可能会有多个线程同时判断,会导致创建多个对象。
加锁实现线程安全
package com.dyit.singleton;
import java.util.concurrent.locks.ReentrantLock;
/**
* 单例模式 懒汉模式
* @author strve
*
*/
public class Singleton {
//开始让实例等于null,需要的时候在进行创建
private static Singleton instance = null;
//创建可重入锁,如果没有锁,可能发生线程不安全。创建多个对象 也可以使用synchronizaed 关键字
private static ReentrantLock lock = new ReentrantLock();
//将构造方法私有化
private Singleton() {
}
//提供一个对外的接口
public static Singleton getSingleton() {
lock.lock();
try {
//如果没有实例 则创建
if (instance==null) {
instance = new Singleton();
}
}finally {
lock.unlock();
}
//返回实例
return instance;
}
}
通过同步锁或者可重入锁来实现线程的安全性
双检锁
package com.dyit.singleton;
import java.util.concurrent.locks.ReentrantLock;
/**
* 单例模式 懒汉模式
* @author strve
*
*/
public class Singleton3 {
private static Singleton3 instance = null;
private Singleton3() {
}
public static Singleton3 getSingleton() {
//双捡锁 如果实例不为null 则直接返回 如果为null 则加锁
if (instance==null) {
synchronized(Singleton3.class) {
if (instance==null) {
instance = new Singleton3();
}
}
}
return instance;
}
}
采用这种方式,可以保证在线程安全的前提下 提高性能。
饿汉式
饿汉式相比于懒汉式就比较简单了,一开始就将实例初始化,然后结构中直接返回即可,缺点就是浪费内存空间,可能不需要用,但是一直占据内存空间
优点:
- 没有加锁,执行效率会提高。
缺点:
- 类加载时就初始化,浪费内存。
java代码:
package com.dyit.singleton;
/**
* 单例模式 饿汉模式
* @author strve
*
*/
public class Singleton2 {
private static Singleton2 instance = new Singleton2();
private Singleton2() {
}
public static Singleton2 getSingleton() {
return instance;
}
}
饿汉模式相比于懒汉模式 因为没加锁效率会更高,但是浪费内存空间。