青海商会网站建设公司,开封网站设计价格,上海站有云网络科技有限公司,郑州网站推广流程文章目录定义类图Java经典实现懒汉Lazy Mode#xff1a;饿汉Eager Mode#xff1a;在饿汉下的多线程案例在懒汉下的多线程案例总结定义
单例模式#xff08;单件模式#xff09;确保一个类只有一个实例#xff0c;并提供一个全局访问点。——HeadFirst
单例模式通过过防…
文章目录定义类图Java经典实现懒汉Lazy Mode饿汉Eager Mode在饿汉下的多线程案例在懒汉下的多线程案例总结定义
单例模式单件模式确保一个类只有一个实例并提供一个全局访问点。——HeadFirst
单例模式通过过防止外部实例化和修改来控制创建的对象的数量。
关键点
私有构造函数没有其他类可以实例化一个新对象。私有引用-没有外部修改。Public static getInstance方法是唯一可以获取对象的地方。
问为什么单例模式能确保实例独一无二 答因为单例模式没有公开的构造器构造器是私有的因此他人无法自己创建实例对象。而且他人想获取实例必须通过调用getInstance静态方法得到实例实例也许是调用时创建的也许是之前已经创建好的。
类图 Java经典实现 私有构造器、一个静态方法、一个静态变量。 懒汉Lazy Mode
public class Singleton{// 使用一个静态变量记录Stingleton的唯一实例private static Singleton uniqueInstance;// 这里是其他有用的实例化变量// 私有构造方法private Singleton(){} public static Singleton getInstance(){if(uniqueInstance null){uniqueInstance new Singleton();}return uniqueInstance;}// 其他有用的方法
}饿汉Eager Mode
public class Singleton2 {// 使用一个静态私有变量记录Stingleton的唯一实例private static Singleton2 uniqueInstance new Singleton2();// 这里是其他有用的实例化变量// 私有构造方法private Singleton2(){}public static Singleton2 getInstance(){return uniqueInstance;}// 其他有用的方法
}在饿汉下的多线程案例
单例类GlobalNum.java
public class GlobalNum {private static GlobalNum gnnew GlobalNum();private int num0;public static GlobalNum getInstance(){return gn;}public synchronized int getNum() //加锁{return num; //返回访问次数}
}主方法SingleMain.java
class NumThread extends Thread{private String threadName;public NumThread(String name){threadNamename;}public void run(){ GlobalNum gnObjGlobalNum.getInstance();for (int i 0; i 5; i) {System.out.println(threadName第gnObj.getNum()次访问);try {this.sleep(1000);} catch (Exception e) {// TODO: handle exceptionSystem.out.println(错误);} }}
}public class SingleMain {
//测试单件模式public static void main(String[] args) {// TODO Auto-generated method stubNumThread thread1new NumThread(线程1);NumThread thread2new NumThread(线程2);thread1.start();thread2.start();}
}JDK8运行结果
线程1第2次访问
线程2第1次访问
线程1第3次访问
线程2第4次访问
线程1第5次访问
线程2第6次访问
线程1第7次访问
线程2第8次访问
线程1第9次访问
线程2第10次访问在懒汉下的多线程案例
getInstance方法添加synchronized关键字防止不同线程创建多个实例对象从而违反单例模式。
public class GlobalNum {private static GlobalNum globalNum;private int num0;// getInstance方法添加synchronized关键字防止创建多个实例public static synchronized GlobalNum getInstance(){if(globalNumnull){globalNum new GlobalNum();return globalNum;}return globalNum;}public synchronized int getNum() //加锁{return num; //返回访问次数}
}主方法SingleMain.java
同上输出结果
线程1第1次访问
线程2第2次访问
线程1第4次访问
线程2第3次访问
线程1第6次访问
线程2第5次访问
线程1第7次访问
线程2第8次访问
线程1第9次访问
线程2第10次访问如果上述getInstance不添加synchronized则会造成输出
线程1第1次访问
线程2第1次访问
线程1第2次访问
线程2第2次访问
线程1第3次访问
线程2第3次访问
线程1第4次访问
线程2第4次访问
线程1第5次访问
线程2第5次访问————————————— 上述懒汉下的多线程案例虽然达到预想效果但是存在缺陷为了防止多个线程创建多个对象给getInstance添加synchronized但实际上只有第一次执行getInstance方法才需要真正的同步当已经创建好对象时后续无需在同步getInstance方法导致后续每次调用getInstance同步变成累赘性能资源浪费。
改进使用双重检查加锁减少使用同步。
添加volatile及synchronized同步块
public class GlobalNum {private static volatile GlobalNum globalNum;private int num0;public static GlobalNum getInstance(){if(globalNumnull){synchronized(GlobalNum.class){if(globalNumnull)globalNum new GlobalNum();}}return globalNum;}public synchronized int getNum() //加锁{return num; //返回访问次数}
}总结
单例模式确保一个程序中的一个类只有一个实例。单例模式提供访问这个实例的全局访问点。Java实现单例模式私有构造器、一个静态变量、一个静态方法。确定性能资源的限制后在多线程情况下谨慎选择合适的方法实现单例模式。
参考 HeadFirst设计模式、https://www.programcreek.com/2011/07/java-design-pattern-singleton/