设计模式中最简单的模式就要数单例模式了。
那么什么是单例模式呢? 保证一个类仅有一个实例,并提供一个访问它的全局访问点。
上图为单例模式的结构示意图。
那么为什么要使用单例模式呢?
简单来说:单例模式的存在,一则,解决多线程并发访问的问题。二则,节约系统内存,提交系统运行的效率,提高系统性能。
下面我们就来看看程序中是怎么实现单例模式的:
一般我们设计一个类都是这样的:
public class Abc
{
private Abc()
{
};
}
然后在其他部分调用:
public class Cbd
{
public Cbd()
{
Abc n1,n2;
n1=new Abc();
n2=new 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();
}
}
写一个小例子,模拟一下我们计算机中的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.控制资源的情况下,方便资源之间的互相通信。如线程池等。