博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
单例模式
阅读量:3954 次
发布时间:2019-05-24

本文共 3682 字,大约阅读时间需要 12 分钟。

单例模式(Singleton)

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

例子:配置文件

源代码:

public class AppConfig{	private String parameterA;	private String parameterB;	public String getParameterA() {		return parameterA;	}	public String getParameterB() {		return parameterB;	}	public AppConfig()	{		readConfig();	}	private void readConfig() {		// TODO Auto-generated method stub		Properties p=new Properties();		InputStream in=null;		try		{			in=AppConfig.class.getResourceAsStream("AppConfig.properties");			p.load(in);			this.parameterA=p.getProperty("paramA");			this.parameterB=p.getProperty("paramB");	}catch(IOException e)		{		 System.out.println("装载配置文件出错");		 e.printStackTrace();		}finally		{			try {				in.close();			}catch(IOException e)			{				 e.printStackTrace();			}		}}}public class main{	public static void main(String[] args) {	Scanner sc=new Scanner(System.in);	AppConfig config=new AppConfig();	String paramA=config.getParameterA();	String paramB=config.getParameterB();	System.out.println("paramA="+paramA+",paramB="+paramB);	}}

问题:系统运行时,会出现很多AppConfig的实例对象,其实用户只想出现一次,造成资源浪费。

解决方法:单例模式

让类自身只提供它的一个实例,并且只提供一个访问它的全局访问点。创建一个唯一的变量对象。

class Singleton{	private static Singleton instance;	private Singleton()	{		//构造方法为private,外界就不能利用new创建此类型的实例	}	public static Singleton GetInstance()	{//获得本类实例的唯一全局访问点		if(instance==null)		{		//如果实例不存在则new一个新实例,否则返回已有的实例			instance=new Singleton();		}		return instance;	}	}public class main{	public static void main(String[] args) {	Scanner sc=new Scanner(System.in);	/*Singleton s0=new Singleton()*/	//错误,外界不能通过new创建此类型	Singleton s1=Singleton.GetInstance();	Singleton s2=Singleton.GetInstance();if(s1==s2)//判断两次实例化后对象的结果是实例相同{	System.out.println("两个对象是相同的实例");}else{	System.out.println("两个对象是不同的实例");}	}}
  • 单例模式因为Singleton类封装它的唯一实例,这样它可以严格地控制客户怎样访问它以及何时访问它,简单地说就是唯一实例的受控访问。
  • 必须给所有其他对象提供这一实例。

 多线程时的单例

多线程的程序,多个线程同时访问Singleton类,调用GetInstance()方法,有可能造成创建多个实例。

解决:在执行new创建实例的地方加上锁,同时在锁定之前判断下是否为null,这样如果已经创建就不用进入锁了。
java使用synchronized上锁

class Singleton{	private static Singleton instance;	private static final Object syncRoot=new Object();	//程序运行时创建一个静态只读的进程辅助对象	private Singleton()	{		//构造方法为private,外界就不能利用new创建此类型的实例	}	public static Singleton GetInstance()	{//获得本类实例的唯一全局访问点		synchronized(syncRoot)//在同一个时刻加了锁的部分程序只有一个线程可以进入		{		if(instance==null)		{		//如果实例不存在则new一个新实例,否则返回已有的实例			instance=new Singleton();		}//不直接synchronized(instance),因为若instance为空,则无法对它加锁		}		System.out.println("singleton创建");		return instance;	}}//使得对象实例由最先进入的那个线程创建,以后的线程在进入时不会再去创建对象实例了。由于//synchronized保证了多线程环境下的同时访问也不会造成多个实例的生成。public class main{	public static void main(String[] args) {	Singleton s1=Singleton.GetInstance();	Singleton s2=Singleton.GetInstance();if(s1==s2)//判断两次实例化后对象的结果是实例相同{	System.out.println("该对象的字符串表示形式:");	System.out.println("s1:"+s1.toString());	System.out.println("s2:"+s2.toString());}	}}

每次调用getinstance方法时都需要锁定,降低了性能。

双重锁定

不用让线程每次都加锁,而是在实例未被创建的时候再加锁处理,同时也能保证多线程的安全。

class SingletonDCL{	private volatile static SingletonDCL singleton;	private SingletonDCL()	{			}	public static SingletonDCL GetInstance()	{		if(singleton==null)		{//各类加锁,类的所有对象用同一把锁			synchronized(SingletonDCL.class)			{				if(singleton==null)//多线程进入,防止第二个线程创建实例,破坏单例原则				{					singleton=new SingletonDCL();				}			}		}		System.out.println("singleton创建");		return singleton;			}}public class main{	public static void main(String[] args) {	SingletonDCL s1=SingletonDCL.GetInstance();	SingletonDCL s2=SingletonDCL.GetInstance();	System.out.println("s1==s2?"+(s1==s2));	System.out.println("该对象的字符串表示形式:");	System.out.println("s1:"+s1.toString());	System.out.println("s2:"+s2.toString());}}

单例模式分类

  • 懒汉式(时间换时间):面临多线程的安全问题需要双重锁定
  • 饿汉式(空间换时间):即静态初始化的方法,类一加载就实例化,所有要提前占用系统资源
    使用单例模式的一个必要条件:在一个系统要求一个类只有一个实例

转载地址:http://txyzi.baihongyu.com/

你可能感兴趣的文章
1016 部分A+B (15 分)
查看>>
1017 A除以B (20 分)
查看>>
1019 数字黑洞 (20 分)
查看>>
1032 挖掘机技术哪家强 (20 分)
查看>>
今夕何夕 HDU - 6112 ( 模拟 )
查看>>
Dividing HDU - 1059 ( 多重背包 - 二进制简化 )
查看>>
Robberies HDU - 2955 ( 0-1背包 )
查看>>
FATE HDU - 2459 ( 二维完全背包 )
查看>>
B. Working out CodeForces - 429B (动态规划)
查看>>
10635 - Prince and Princess UVA-10635 (最长公共子序列的O(nlogn)的解法:LCS转换为LIS)
查看>>
Sizeof和Strlen
查看>>
lower_bound和upper_bound
查看>>
Subsequence POJ - 3061 ( 尺取法 )
查看>>
常见HTTP状态码大全
查看>>
这16个数据可视化案例,惊艳了全球数据行业
查看>>
大数据死亡率报告揭秘:SUV与轿车到底谁更危险?
查看>>
2017年网络流行语TOP20 , 没用过算我输!
查看>>
看完这13张图,不得不佩服还是外国人会玩人工智能
查看>>
从零开始用Python构造决策树(附公式、代码)
查看>>
精华 | 12个关键词告诉你告诉你什么是机器学习(基础篇)
查看>>