Java【设计模式】单例模式七种实现方式(附源码)

单例模式介绍

所谓类的单例模式设计,就是采取一定的方法保证在整个系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态)

单例模式常用实现方式

饿汉式

步骤如下:

  1. 构造方法私有化
  2. 类内创建对象(创建就进行实例化)
  3. 向外提供一个静态公共方法
public class SingletonTest01 {
	public static void main(String[] args) {
		Singleton st=Singleton.getInstance();//类装载时便进行实例化
		Singleton st2=Singleton.getInstance();
		System.out.println(st==st2);
		System.out.println(st.hashCode());
		System.out.println(st2.hashCode());
	}
}
class Singleton{
	
	//饿汉式
	//1.构造器私有化
	private Singleton()
	{
	}
	//2.本类内部创建对象实例
	private final static Singleton instance =new Singleton();
	//3。提供一个公有静态方法
	public static Singleton getInstance()
	{
		return instance;
	}
}

优点:线程安全(实现同步)
缺点:传参数困难,且容易造成内存浪费(装载即实例,但是有可能用不到)

懒汉式

步骤如下:

  1. 构造方法私有化
  2. 类内创建对象
  3. 向外提供一个静态公共方法(需要判断是否非空)
public class SingletonTest03 {
	public static void main(String[] args) {
		System.out.println("线程不安全!!!!");
		Singleton st=Singleton.getInstance();//类装载时便进行实例化
		Singleton st2=Singleton.getInstance();
		System.out.println(st==st2);
		System.out.println(st.hashCode());
		System.out.println(st2.hashCode());
	}
}
class Singleton{
	private static Singleton instance;
	private Singleton()
	{
	}
	public static Singleton getInstance()
	{
		if(instance==null)
			instance=new Singleton();
		return instance;
	}
	
}

优点:延迟加载
缺点:线程不安全(多线程下,若一个线程进入了if(singleton==null)判断语句块,还未来得及往下执行,另一个线程也通过了这个判断语句,这时便会产生多个实例)

同步方法

synchronized同步方法,每一次只允许一个线程访问。

public class SingletonTest04 {
	public static void main(String[] args) {
		Singleton st=Singleton.getInstance();
		Singleton st2=Singleton.getInstance();
		System.out.println(st==st2);
		System.out.println(st.hashCode());
		System.out.println(st2.hashCode());
	}

}
class Singleton{
	private static Singleton instance;
	private Singleton()
	{
		
	}
	public static synchronized Singleton getInstance()
	{
		//此方法效率低下
		if(instance==null)
			instance=new Singleton();
		return instance;
	}
}

优点:解决了线程不安全的问题
缺点:效率太低(每个线程在想获得类的实例的时候,执行getInstance()方法都要进行同步。其实只执行一次代码实例化就足够了。)

同步代码块
class Singleton
{
	private static Singleton instance;
	private Singleton()
	{
		
	}
	public static Singleton getInstance()
	{
		if(instance==null)
		{
			synchronized(Singleton.class)
			{
				instance=new Singleton();
			}
		}
		return instance;
	}
}

写法错误,同步并不能起到真正的作用,实际开发不可用。

双重检查
class Singleton{
	private static volatile Singleton instance;
	private Singleton()
	{
		
	}
	public static synchronized Singleton getInstance()
	{
		if(instance==null)//解决了效率低下
		{
			synchronized(Singleton.class)
			{
				if(instance==null)//双重检查,实现一次实例化
				{
					instance=new Singleton();
				}
			}
		}
		return instance;
	}
}

实现了延时加载,与线程安全,同时保证了效率。

静态内部类
class Singleton
{
	private static volatile Singleton instance;
	private Singleton()
	{
	}
	//外类装载不会马上装载的
	private static class SingletonInstance{
		private static final Singleton Instance=new Singleton();//饿汉式
	}
	//用到他的时候才装载(JVM装载时线程安全)
	public static synchronized Singleton getInstance()
	{
		return SingletonInstance.Instance;//懒汉式
	}
}

优点:

  1. 这种方法采用了类装载的机制来保证初始化实例时只有一个线程。
  2. 静态内部类在Singleton进行装载时并不会立即实例化,而是在需要进行实例化时,调用getInstance()方法,才会装载SingletonInstance类,从而完成实例化。
  3. 类的静态属性只会在第一次加载类的时候初始化,JVM保证了线程的安全,在类进行初始化时,别的线程是无法进入的。
    这种方法也实现了延时加载与线程安全
枚举方式
public class SingletonTest08 {
	public static void main(String[] args) {
		Singleton st=Singleton.Instance;
		Singleton st2=Singleton.Instance;
		System.out.println(st==st2);
		System.out.println(st.hashCode());
		System.out.println(st2.hashCode());
	}

}
enum Singleton{//枚举实现单利
	Instance;//属性
	public void sayOK()
	{
		System.out.println("ok~");
	}
}

优点:
枚举方式实现单例,不仅能够避免多线程同步问题,而且还能防止反序列化重新创建新的对象。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值