单例模式

0.单例模式知识体系


单例模式知识可以用下图表示,掌握下图就系统掌握单例模式。

1.单例模式概论


1)引论


 古代一个国家皇帝只能有一个,如果多了,国家就会出问题;现代一个家庭老婆只能有一个,如果多了,家就会出问题(现在新闻上还时不时爆出妻子与小三街头互殴的事情),弄得爷们儿不知道怎么办了;有些时候,软件中某些类的对象也只能有一个,多了软件就会出问题(如造成不一致的结果)或浪费资源,如配置文件、工具类、线程池、缓存、日志对象等。


2)定义


一个类有且仅有一个实例,并且自行实例化向整个系统提供。单例模式有一个统一规则(即单例模型),而根据规则执行情况又可分为饿汉模式与懒汉模式,下面展开详细论述。 


2.单例模型与饿汉模式与懒汉模式


0)单例模型


(1)私有化构造器,因为创建实例需要构造器,为保证外界不能创建实例,所以私有化,即private修饰。

(2)内部创建或声明实例,私有化构造器后,外界无法创建实例,需要内部创建。

(3)提供获取方法,上面实例创建后存放在私有字段中,不允许外界访问,此时就需要提供类方法获取实例。


1)饿汉模式


所谓饿汉就是感觉类的实例像是食物,即使用户不获取也要先得到。

(1)私有化构造器:private Singleton(){} 

 (2)内部创建实例:private static final Singleton instance = new Singleton(); 

 (3)提供获取方法:public static Singleton getInstance(); 

下面是详细代码:

class Singleton {
	//2.内部创建实例
	private static final Singleton instance = new Singleton();
	//1.私有化构造器
	private Singleton(){}
	//3.提供获取方法
	public static Singleton getInstance(){
		return instance;
	}
	//成员方法
	public void show(){
		System.out.println("单例模式的饿汉模式");
	}
}
public class SingletonTest{
	public static void main(String[] args){
		Singleton.getInstance().show();
	}
}


2)懒汉模式


所谓懒汉就是直到用户获取才会创建,很懒,不会早创建一会儿。

(1)私有化构造器:private Singleton(){}

(2)内部声明实例:private static Singleton instance;注意只是声明

(3)提供获取方法:if(instance == null){ instance = new Singleton;} return instance;

class Singleton {
	//2.内部声明实例
	private static Singleton instance;
	//1.私有化构造器
	private Singleton(){}
	//3.提供获取方法
	public static Singleton getInstance(){
		if(instance == null){
			instance = new Singleton();
		}
		return instance;
	}
	//成员方法
	public void show(){
		System.out.println("单例模式的懒汉模式");
	}
}
public class SingletonTest{
	public static void main(String[] args){
		Singleton.getInstance().show();
	}
}

3.饿汉模式与懒汉模式区别


1)饿汉模式


(1)加载慢,运行快,因为类加载时就会创建对象,不管用户是否使用。

(2)线程安全的。


2)懒汉模式


(1)加载快,运行慢,加载时没有创建对象。

(2)线程不安全的,多线程时有共享数据并且访问此共享数据的代码有多条,可能就会因为CPU切换的随机性而造成构造器的多次调用使不再单例。

如下面代码,多运行几次就会发现构造器会被多次调用

class Singleton 
{
	//2.内部声明实例
	private static Singleton instance;
	//1.私有化构造器
	private Singleton(){}
	//3.提供获取方法
	public static Singleton getInstance(){
		if(instance == null){
			instance = new Singleton();
			System.out.println(Thread.currentThread().getName()+"调用一次构造器");
		}
		return instance;
	}
	//成员方法
	public void show(){
		System.out.println("单例模式的懒汉模式");
	}
}

class User implements Runnable{
	public void run(){
		for(int i =0; i < 3; i++){
			Singleton.getInstance().show();
		}
	}
}
public class SingletonTest{
	public static void main(String[] args){
		User u = new User();
		Thread t0 = new Thread(u);
		Thread t1 = new Thread(u);
		Thread t2 = new Thread(u);
		t0.start();
		t1.start();
		t2.start();
	}
}

可以用双if和同步代码块方式来解决此问题。

//采用双if与同步代码块来解决上述问题
class Singleton {
	//2.内部声明实例
	private static Singleton instance;
	//1.私有化构造器
	private Singleton(){}
	//3.提供获取方法
	public static Singleton getInstance(){
		//双重if
		if(instance == null){
			synchronized(Singleton.class){
				//同步代码块,注意因为方法为静态的,不能使用this作为同步锁
				if(instance == null){
					instance = new Singleton();
					System.out.println(Thread.currentThread().getName()+"调用一次构造器");
				}
			}
		}
		return instance;
	}
		//成员方法
	public void show(){
		System.out.println("单例模式的懒汉模式");
	}
}
class User implements Runnable{
	public void run(){
		for(int i =0; i < 3; i++){
			Singleton.getInstance().show();
		}
	}
}
public class SingletonTest{
	public static void main(String[] args){
		User u = new User();
		Thread t0 = new Thread(u);
		Thread t1 = new Thread(u);
		Thread t2 = new Thread(u);
		t0.start();
		t1.start();
		t2.start();
	}
}

4.单例模式应用


待补充...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值