场景:
当超市老板需要对到店消费人数进行实时监控的时候,需要有人对进出的人数进行盘点,每进一个加一,每出一个则减一。在超市门口设置负责统计的机器。
饿汉式
public class SessionCount {
private AtomicInteger count = new AtomicInteger(0);
private static SessionCount instance = new SessionCount();//懒汉式
private SessionCount(){
}
public static SessionCount getInstance(){
return instance;
}
/***以下是业务方法***/
public int plus(){
return count.incrementAndGet();
}
public int decrease(){
return count.decrementAndGet();
}
public void showMessage(){
System.out.println("当前人数:"+this.count.get());
}
}
饿汉式保持唯一性的做法是在实例化SessionCount对象时使其静态化,即使其变成静态对象。
具体调用类
/**
* 统计在线人数
*/
public class SessionCountClient {
public static void main(String[] args) {
//营业开门
SessionCount count = SessionCount.getInstance();
count.plus();
count.showMessage();
SessionCount count1 = SessionCount.getInstance();
count1.plus();
count1.showMessage();
//出去一个
SessionCount count2 = SessionCount.getInstance();
count2.decrease();
count2.showMessage();
}
}
此时,老板会发现,如果时间长了而且平时客流量并不大的时候,使用饿汉式这种方法会造成机器浪费资源。这样老板就会想:能不能在有客人来的时候再把机器打开呢?此时懒汉式方法就出现了。
public class SessionCount {
private AtomicInteger count = new AtomicInteger(0);
private static SessionCount instance;
private SessionCount(){
}
//获取唯一可用的对象
//懒汉式
public static SessionCount getInstance(){
if (instance == null){//双重校验锁
synchronized (SessionCount.class){
if (instance == null){
instance = new SessionCount();
}
}
}
return instance;
}
/***以下是业务方法***/
public int plus(){
return count.incrementAndGet();
}
public int decrease(){
return count.decrementAndGet();
}
public void showMessage(){
System.out.println("当前人数:"+this.count.get());
}
}
这里需要注意的是,当系统运行时会有多个线程在同时运行,并且当前这个线程必须是唯一的,不能重复创建。则需要判断当前机器(对象)是否没开(为空)。同时保持有且仅有一个机器(对象)在运行。以免重复构造浪费资源。
总结
作用:保证一个类仅有一个实例,并提供一个访问它的全局访问点
具体
1、为防止实例创建多个,将构造函数限制为private;
2、建一个类静态变量,持有一个自己的实例;
3、通过静态方法对外部提供这一实例;
4、相对于饿汉单例模式,懒汉式还需要在多线程环境下保持其唯一性,需要进行双重锁验证。
对静态实例的初始化有两种方式:饿汉式、懒汉式