Java单例五种实现模式解析
什么是单例模式?
单例模式是指一个类只能被实例化一次,并且全局都可以访问到这个实例。在实际开发中,很多情况下我们只需要一个实例,例如全局配置信息、日志管理等等,这时候使用单例模式可以节省系统资源,减少不必要的开销。
单例模式的特点
- 保证一个类只有一个实例。
- 提供一个访问该实例的全局入口。
- 不能被其他对象实例化。
五种实现模式
1. 饿汉式
线程安全
饿汉式在类被加载的同时就创建好了唯一的实例,故天然的线程安全。
public class Singleton {
private static final Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
示例说明
public static void main(String[] args) {
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1 == instance2);
}
输出结果为 true
,表明两个实例指向同一内存空间,即单例模式被实现。
2. 懒汉式
线程不安全
懒汉式在第一次使用的时候才创建实例,需要考虑线程安全性问题,否则会出现多个实例的情况。
public class Singleton {
private static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
线程安全
使用双重判定锁的方式可以保证线程安全性。
public class Singleton {
private static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
示例说明
public static void main(String[] args) {
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1 == instance2);
}
输出结果为 true
,表明两个实例指向同一内存空间,即单例模式被实现。
3. 静态内部类
这种方式利用了 Classloader 的机制来保证初始化实例时只有一个线程。静态内部类不会在类加载时就初始化,而是当被调用时才进行初始化。
public class Singleton {
private Singleton(){}
private static class SingletonHolder{
private static final Singleton instance = new Singleton();
}
public static final Singleton getInstance(){
return SingletonHolder.instance;
}
}
示例说明
public static void main(String[] args) {
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1 == instance2);
}
输出结果为 true
,表明两个实例指向同一内存空间,即单例模式被实现。
4. 枚举类型
枚举类型被限制了元素个数,保证了单例模式的实现,且避免了线程安全问题。
public enum Singleton {
INSTANCE;
public void whateverMethod() { }
}
示例说明
public static void main(String[] args) {
Singleton instance1 = Singleton.INSTANCE;
Singleton instance2 = Singleton.INSTANCE;
System.out.println(instance1 == instance2);
}
输出结果为 true
,表明两个实例指向同一内存空间,即单例模式被实现。
5. 双重校验锁
这种方式可以在保证线程安全的情况下实现懒加载。
public class Singleton {
private volatile static Singleton instance = null;
private Singleton(){}
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
}
示例说明
public static void main(String[] args) {
Singleton instance1 = Singleton.getInstance();
Singleton instance2 = Singleton.getInstance();
System.out.println(instance1 == instance2);
}
输出结果为 true
,表明两个实例指向同一内存空间,即单例模式被实现。
总结
以上五种单例实现方式各有优缺点,应根据具体情况选择。选用不合适的单例实现方式会导致系统资源浪费、性能降低及线程安全问题等。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:java单例五种实现模式解析 - Python技术站