常用设计模式之单例设计模式+JAVA实例

介绍:
概念:
单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)
正文:
单例模式没有什么可说的,大家多多少少都了解过一点,最有名的是"饿汉式”,“懒汉式”。单例的实现重要的一点是构造方法私有化,然后只返回一个对象,我们先写一个"饿汉式"。

public class Singleton {

	//静态是因为实例还没初始化出来,所以可以通过类名来调用,下面的静态方法一个道理
	//final修饰保证不可变唯一
	//为什么叫饿汉,因为它很饿,JVM在加载这个类的时候,它就迫不及待的去创建唯一的单件实例
	//保证任何线程访问之前先创建出来(很重要)。
	private static final Singleton uniqueInstance = new Singleton();

	private Singleton() {

	}

	public static Singleton getInstance(){

		return uniqueInstance;
	}
}

缺点也很明显,我如果不用这个实例,你的资源不就浪费了。
我们改进一下,当你用的时候,再加载不就完事了,这就是延迟加载也就是经常说的"懒汉式"。

public class Singleton {

	private static Singleton uniqueInstance;

	private Singleton() {

	}
	
	public static Singleton getInstance(){
		//判断一下,如果还没有实例,我在实例化,我很懒
		if(uniqueInstance == null){
			uniqueInstance = new Singleton();
		}
		return uniqueInstance;
	}
}

那个资源浪费的问题看起来解决了,我们没有浪费资源,然而并没有,"懒汉式"在多线程环境下,有大问题。
我们弄两个线跑一下看有什么问题,我在创建对象后输出一下地址。

		 public static Singleton getInstance(){
		if(uniqueInstance == null){
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			uniqueInstance = new Singleton();
			System.out.println(uniqueInstance);
		}
		return uniqueInstance;
	}
//启动两个线程
public class MyThread{

	public static void main(String[] args) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				Singleton instance = Singleton.getInstance();
			}
		}).start();

		new Thread(new Runnable() {
			@Override
			public void run() {
				Singleton instance = Singleton.getInstance();
			}
		}).start();
	}


}
输出:
com.singleton.Singleton@4be63fd3
com.singleton.Singleton@3943de20

完犊子,输出两个地址,这明显不是单例了,我用一个图解释一下这个情况。
图片来自Head First 设计模式
解决方法很简单,在getInstance加上synchronized,有人会说效率问题,现在synchronized效率已经很高了,我觉得可以忽略。
关键字的位子我觉得可以换换,我们只需保证有线程安全问题的地方不会出问题。这就是最后一种DCL双重锁机制。

public class Singleton {

	private static  Singleton uniqueInstance;

	private Singleton() {

	}
	public static Singleton getInstance(){
	// 第一次检查instance是否被实例化出来,如果没有进入if块
		if(uniqueInstance == null){
			synchronized (Singleton.class){
			// 某个线程取得了类锁,实例化对象前第二次检查instance是否已经被实例化出来,如果没有,才最终实例出对象
				if(uniqueInstance == null){
					uniqueInstance = new Singleton();
				}

			}


		}

		return uniqueInstance;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

农业路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值