设计模式中最简单的模式就要数单例模式了。
那么什么是单例模式呢? 保证一个类仅有一个实例,并提供一个访问它的全局访问点。
上图为单例模式的结构示意图。
那么为什么要使用单例模式呢?
简单来说:单例模式的存在,一则,解决多线程并发访问的问题。二则,节约系统内存,提交系统运行的效率,提高系统性能。
下面我们就来看看程序中是怎么实现单例模式的:
一般我们设计一个类都是这样的:
public class Abc{ PRivate Abc() { }; }然后在其他部分调用:
public class Cbd{ public Cbd() { Abc n1,n2; n1=new Abc(); n2=new Abc(); }}但这样Abc这个类就会出现好多实体并不好控制,下面我们来改变一下啊Abc这个类的结构从而实现单例模式:public class Abc{ private static Abc uniqeInstance_Abc = null; //通过内置私有静态参数实现单例状态 private Abc(){ }; //外部只能调用单例,单例实体有类内部控制 public static Abc getInstance_Abc() { if(uniqeInstance_Abc==null) { uniqeInstance_Abc=new Abc(); } return uniqeInstance_Abc; }}这样我们变实现了单例模式public class Cbd{ public Cbd() { Abc n1,n2; n1=Abc.getInstance_Abc(); }}可以看到Abc这个类的构造函数变成了private修饰,所以并不能在其他类中new出来只能通过调用getxxx函数来使用,这就保证了单例性。写一个小例子,模拟一下我们计算机中的CPU处理程序:
package com.java.jikexueyuan.singleton;public class Cpu { private boolean idle; private boolean compute; public volatile static Cpu uniqueInstance_cpu = null; int num; private Cpu() { idle = true; compute = false; num = 101; } public static Cpu getInstance() { if (uniqueInstance_cpu == null) { synchronized (Cpu.class) { if (uniqueInstance_cpu == null) { uniqueInstance_cpu = new Cpu(); } } } return uniqueInstance_cpu; } //判断cpu是否为空闲状态 public boolean isIdle() { if (idle) { idle = false; compute = false; System.out.println("cpu空闲"); return true; } else { System.out.println("cpu繁忙"); return true; } } //cpu计算结束 public void compute_over() { if ((!idle) && compute) { idle = true; compute = false; System.out.println("cpu计算完成"); } } //启动cpu计算过程 public void computing() { if ((!idle) && (!compute)) { compute = true; System.out.println("cpu正在计算,计算cpu编号为" + num); } }}我们来调用一下:public class test { public static void main(String[] args) { for(int i = 0; i < 5 ; i++) { Cpu c1 = Cpu.getInstance(); if(c1.isIdle()) { c1.computing(); c1.compute_over(); } } }}其实这样设计的单例模式有一个重大隐患,就是当两个线程同时创建一个Abc类的时候,可以会new出来两个实体而导致严重的错误。。。
解决传统的解决方式呢,有三种:
第一种:添加同步锁:
public class Abc{ private static Abc uniqeInstance_Abc = null; //通过内置私有静态参数实现单例状态 private Abc(){ }; //外部只能调用单例,单例实体有类内部控制 //添加了同步所,保证不会有两个线程同是进入该方法 public static synchronized Abc getInstance_Abc() { if(uniqeInstance_Abc==null) { uniqeInstance_Abc=new Abc(); } return uniqeInstance_Abc; }}第二种:急切创建法:public class Abc{ //通过内置私有静态参数实现单例状态 //直接创建实例 private static Abc uniqeInstance_Abc = new Abc(); private Abc(){ }; //外部只能调用单例,单例实体有类内部控制 public static Abc getInstance_Abc() { if(uniqeInstance_Abc==null) { uniqeInstance_Abc=new Abc(); } return uniqeInstance_Abc; }}第三种:双重检查加锁法public class Abc{ //通过内置私有静态参数实现单例状态 //volatile关键字确保多线程在处理时的正确性 private volatile static Abc uniqeInstance_Abc = new Abc(); private Abc(){ }; //外部只能调用单例,单例实体有类内部控制 public static Abc getInstance_Abc() { //多重加锁 if (uniqeInstance_Abc == null) { synchronized (Abc.class) { if (uniqeInstance_Abc == null) { uniqeInstance_Abc = new Abc(); } } } return uniqeInstance_Abc; }}单例模式的使用场景:
1.资源共享的情况下,避免由于资源操作时导致的性能或损耗等。如上述中的日志文件,应用配置。 2.控制资源的情况下,方便资源之间的互相通信。如线程池等。
新闻热点
疑难解答