您的位置:首页 > 其它

单例模式

2015-07-13 16:23 260 查看
  我们在写程序的时候,大部分时候,会把类定义成为public类型的,那么任何类都可以随意的创建该类的对象。但是有时候,这种做法并没有任何意义,频繁的创建对象和回收对象造成内存损耗,所以就有了单例模式

  一个类只能创建一个对象,则这个类被成为单例类,这种模式被成为单例模式

  单例模式的原则是:

    1.把类的构造方法隐藏起来

    2.创建一个方法,这个方法可以创建一个(并且只有一个)自己的实例

    3.这个方法可以被外部使用

  单例模式分为:懒汉模式、饿汉模式和等级模式

  懒汉模式:


  /**
*懒汉模式,特征是待到使用时,才创建该类对象
*/

publicclassSingle{


//定义一个类变量,来存储该类对象
privatestaticSinglesingle;

//隐藏构造器
privateSingle(){

}

//定义一个方法供外部调用,返回一个该类唯一的对象
publicstaticSinglegetSingle(){
if(single==null){
single=newSingle();
}
returnsingle;
}

publicstaticvoidmain(String[]args){
Singles1=Single.getSingle();
Singles2=Single.getSingle();
if(s1==s2){
System.out.println("Single类是单例模式");
}else{
System.out.println("Single类不是单例模式");
}
}
}


  饿汉模式:


   /**
*饿汉模式饿汉模式特征是在类加载时候已经创建好实例待调用,并且该实例不可变
*/


publicclassSingle{

//直接创建该类的实例,该实例不可变
privatestaticfinalSinglesingle=newSingle();

//隐藏构造函数
privateSingle(){

}

//创建一个方法供外部调用,返回该类的实例
publicstaticSinglegetSingle(){
returnsingle;
}

publicstaticvoidmain(String[]args){
Singles1=Single.getSingle();
Singles2=Single.getSingle();
if(s1==s2){
System.out.println("Single类是单例模式");
}else{
System.out.println("Single类不是单例模式");
}
}
}


  登记模式:

importjava.util.HashMap;
importjava.util.Map;
importjava.util.Set;

/**
*单例模式之登记模式,特征是事先维护一组map存放一个实例,当创建实例时,先查看map是否存在,如果存在,则直接返回,如果不存在,则先存入,再返回
*/
publicclassSingle{

//定义一个map,用来登记实例
privatestaticMap<String,Single>map=newHashMap<String,Single>();
//先在map中存放一个Single实例
static{
Singlesingle=newSingle();
map.put(single.getClass().getName(),single);
}

//隐藏构造器
privateSingle(){

}

//定义一个方法供外部调用,用来返回实例,需要传入一个参数作为map中的“键”
publicstaticSinglegetSingle(Stringkey){
//如果传入的参数为null,则讲类名称赋值给它
if(key==null){
key=Single.class.getName();
}
//根据传入的“键”判断是否存在“值”,如果不存在,则将该
if(map.get(key)==null){
try{
map.put(key,(Single)Class.forName(key).newInstance());
}catch(InstantiationExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}catch(IllegalAccessExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}catch(ClassNotFoundExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
returnmap.get(key);
}

publicstaticvoidmain(String[]args){
Singlesingle1=Single.getSingle(null);
Singlesingle2=Single.getSingle(null);
System.out.println(single1==single2);
}
}


单例中的线程安全问题

饿汉式这种一开始就创建实例的方式,线程是安全的,懒汉式则不同,看代码

publicclassSingle{

//定义一个类变量,来存储该类对象
privatestaticSinglesingle;

//隐藏构造器
privateSingle(){

}

//定义一个方法供外部调用,返回一个该类唯一的对象
publicstaticSinglegetSingle(){
if(single==null){//当线程执行到这里挂起时,别的线程获取执行权限执行到这里,还会继续给single创建实例,这样就造成了线程安全问题。
single=newSingle();
}
returnsingle;
}

publicstaticvoidmain(String[]args){
Singles1=Single.getSingle();
Singles2=Single.getSingle();
if(s1==s2){
System.out.println("Single类是单例模式");
}else{
System.out.println("Single类不是单例模式");
}
}
}


  为了避免懒汉式的线程安全问题,我们需要给他加上代码同步

publicclassThreadForSingle{
publicstaticvoidmain(String[]args){

}
}

classSingle{

privateSingle(){
}

privatestaticSinglesingle=null;

publicstaticSinglegetSingle(){

synchronized(Single.class){
if(single==null){
single=newSingle();
}
}
returnsingle;
}
}


  当线程进来判断出single为null时,遇到问题挂起,其余的线程则无法进来,这样就保证了线程的安全

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: