Java单例模式

本文探讨了Java设计模式中的单例模式,强调其在配置文件、工具类等场景中的适用性。单例模式通过私有化构造方法并提供静态获取实例的方法来确保类的唯一实例。文章介绍了饿汉模式、懒汉模式和双重检查枷锁三种实现方式,并指出在类加载和线程安全方面的差异。同时,提到了单例模式在不同类加载器和序列化情况下的潜在问题及解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单例是Java设计模式中最简单的模式


使用设计模式的目的: 使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码的可靠性


单例模式使用情形:在有些情况下,对象有且只有一个的时候可以使用单例模式,比如:配置文件,工具类,线程池,日志,缓存对象等


单例模式的要点:


1.将构造方法私有化,不允许外部直接创建对象


2.创建类的唯一实例,使用private static 修饰


3.提供一个用于获取实例的方法,使用private static 修饰


单例模式的类型


饿汉模式:加载类时比较慢,但运行时获取对象的速度比较快;线程安全。


懒汉模式:加载类时比较快,但运行时获取对象的速度比较慢;线程不安全。


双重检查枷锁: 加载类时比较快,但运行时获取对象的速度比较慢;线程安全


例子:


饿汉模式

<span style="font-size:18px;">/*
 * 单例模式Singleton
 * 应用场合:有些对象只需要一个就足够了,如古代皇帝、老婆
 * 作用:保证整个应用程序中某个实例有且只有一个
 * 类型:饿汉模式
 */
public class Singleton {
	//1.将构造方法私有化,不允许外部直接创建对象
	private Singleton(){		
	}
	
	//2.创建类的唯一实例,使用private static修饰
	private static Singleton instance=new Singleton();
	
	//3.提供一个用于获取实例的方法,使用public static修饰
	public static Singleton getInstance(){
		return instance;
	}
}
</span>
懒汉模式

<span style="font-size:18px;">/*
 * 懒汉模式
 * 区别:饿汉模式的特点是加载类时比较慢,但运行时获取对象的速度比较快,线程安全
 *      懒汉模式的特点是加载类时比较快,但运行时获取对象的速度比较慢,线程不安全
 */
public class Singleton2 {
	//1.将构造方式私有化,不允许外边直接创建对象
	private Singleton2(){
	}
	
	//2.声明类的唯一实例,使用private static修饰
	private static Singleton2 instance;
	
	//3.提供一个用于获取实例的方法,使用public static修饰
	public static Singleton2 getInstance(){
		if(instance==null){
			instance=new Singleton2();
		}
		return instance;
	}
}
</span>

双重检查加锁

package singleton;

/**
 * 单例模式-双重检查加锁
 * */
public class Singleton2 {
	private volatile static Singleton2 uniqueInstance;

	private Singleton2() {
	}

	public static Singleton2 getInstance() {
		if (uniqueInstance == null) {

			synchronized (uniqueInstance) {
				if (uniqueInstance == null)
					uniqueInstance = new Singleton2();
			}
		}
		return uniqueInstance;
	}
}


问题:


有两个问题需要注意:


1.如果单例由不同的类装载器装入,那便有可能存在多个单例类的实例。假定不是远端存取,例如一些servlet容器对每个servlet使用完全不同的类装载器,这样的话如果有两个

servlet访问一个单例类,它们就都会有各自的实例。


2.如果Singleton实现了java.io.Serializable接口,那么这个类的实例就可能被序列化和复原。不管怎样,如果你序列化一个单例类的对象,接下来复原多个那个对象,那你就会

有多个单例类的实例。


对第一个问题修复的办法是:


<span style="font-size:18px;">private static Class getClass(String classname)      
                                         throws ClassNotFoundException {     
      ClassLoader classLoader = Thread.currentThread().getContextClassLoader();     
      
      if(classLoader == null)     
         classLoader = Singleton.class.getClassLoader();     
      
      return (classLoader.loadClass(classname));     
   }     
}  </span>

 对第二个问题修复的办法是:

public class Singleton implements java.io.Serializable {     
   public static Singleton INSTANCE = new Singleton();     
      
   protected Singleton() {     
        
   }     
   private Object readResolve() {     
            return INSTANCE;     
      }    
}   



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值