设计模式:单例模式Singleton

单例模式

     保证一个类只有一个实例,并且提供一个访问他的全局访问点  --《设计模式:可复用面向对象软件的基础》84页3.5节

在某些情况下我们需要一个类在任何情况下 只需要同一个实例并且提供一个访问该实例的方法

单例模式又分懒汉和饿汉模式

懒汉模式在你需要他的时候才会去创建对象,也就是你在调用访问该实例的方法的时候才会去创建


/**
 * 单例模式 :懒汉模式
 * 
 * @author 爱出走的眼睛
 *
 */
public class Singleton {
	private static Singleton singleton;

	private Singleton() {
       System.out.println("创建对象");
	}
    
	public static Singleton GetInstance() {
		if (singleton==null) {
			singleton=new Singleton();
		}
		return singleton;
		
	}
}

       //测试代码
           Singleton s1 = Singleton.GetInstance();	   
	   Singleton s2 = Singleton.GetInstance();
	   System.out.println(s1==s2);

       //结果为 true
	

上述代码并非严格,因为没有考虑到多线程的环境下  下面我测试一下在多线程情况下出现的问题

public class Test {
	public static void main(String[] args) {

		Thread tA = new Thread() {
			public void run() {
				Singleton.GetInstance();
			}
		};

		Thread tB = new Thread() {
			public void run() {
				Singleton.GetInstance();
			}
		};
		tA.start();
		tB.start();
	}
}


打印结果为: 
    创建对象
    创建对象

因为在多线程的情况下  线程A可能在创建对象之前cpu时间片用完了进入就绪状态,线程B分配到资源 这个时候由于线程A没有执行完创建对象语句,此时线程B判断依然对象为空,所以线程B也会去创建对象,这样两个线程都进入了if里面 导致单例模式失败! 

严格的单例模式 懒汉

/**
 * 单例模式 :严格的懒汉模式
 * 
 * @author 爱出走的眼睛
 *
 */
public class Singleton {
         //使用volatile 关键字 禁止指令排序
	private static volatile Singleton singleton;

	private Singleton() {

	}
    
	public static Singleton GetInstance() {
        //这里 锁代码块比锁方法更加高效
		if (singleton==null) {
			synchronized(Singleton.class) {
				if (singleton == null) {
					singleton = new Singleton();
				}
			}
			
		}
		return singleton;		
	}
}

如果不懂volatile 和线程的话 需要自己补习一下同步锁和volatile 关键字

饿汉模式: 不管你调用不调用 它都会去创建这个对象

饿汉代码就简单很多

public class SingletonHungry {
    //注意这里使用了final关键字
	private static final SingletonHungry singleton=new SingletonHungry();
	    
	private SingletonHungry() {

	}
	
	public static SingletonHungry GetInstance() {
		
		return singleton;
		
	}
}

应用场景

最简单的一个小例子  windows系统中的任务管理器 无论你打开多少次任务管理器 他只会有一个窗口

因为如果你打开两个任务管理器窗口 且内容一样 管理器需要去调用CPU去获取这些信息 这样设计的目的是为了减少资源浪费 所以设计成单例模式,第二点 如果你打开两个管理器发现内容不一样 这样更容易给用户带来误解。

spring中的bean默认就是单例模式

线程池,数据库连接池,日志对象这些也用到了单例模式

  • 11
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值