创业服务网站建设方案项目书,电商怎么做新手入门视频,怎样进入公众号,我的深圳app官网下载文章目录 1. 什么是单例模式#xff1f;2. 立即加载/“饿汉模式”3. 延时加载/“懒汉模式”3.1 第一版3.2 第二版3.3 第三版3.4 第四版 1. 什么是单例模式#xff1f; 提起单例模式#xff0c;就必须介绍设计模式#xff0c;而设计模式就是在软件设计中#xff0c;针对特殊… 文章目录 1. 什么是单例模式2. 立即加载/“饿汉模式”3. 延时加载/“懒汉模式”3.1 第一版3.2 第二版3.3 第三版3.4 第四版 1. 什么是单例模式 提起单例模式就必须介绍设计模式而设计模式就是在软件设计中针对特殊问题提出的解决方案。它是多年来针对一些常见的问题的解决方法具有良好的可复用性、可扩展性和可维护性。 标准的设计模式有23种单例模式就是最常见的一种其目的是确认一个类只有一个实例对象并且可以提供一个全局访问点来访问该实例。 单例就是指一个类的实例只有一个即该类的所有对象都指向用同一个实例。 而多数单例模式并没有结合多线程在多线程环境下运行有时会出现线程安全问题所以下面不仅介绍如何实现单例模式还有单例模式结合多线程使用时的相关知识。 2. 立即加载/“饿汉模式” 立即加载一般还被称作饿汉模式根据立即饿汉可以看出十分的急所以在饿汉模式中这样单例中的唯一实例对象就被创建。 创建MyObject.java代码如下
//单例模式、饿汉模式
public class MyObject {//进行封装防止创建新的对象private static MyObject object new MyObject();private MyObject(){};//通过这个方法获得对象public static MyObject getObject(){return object;}
}创建线程类MyThread.java
public class MyThread extends Thread{Overridepublic void run() {System.out.println(MyObject.getObject().hashCode());}
}创建运行类Run.java:
public class Run {//测试单例模式对象是同一个public static void main(String[] args) {MyThread t1 new MyThread();MyThread t2 new MyThread();MyThread t3 new MyThread();t1.start();t2.start();t3.start();}
}运行结果 运行结果相同说明对象是同一个成功实现了立即加载型单例设计模式。
3. 延时加载/“懒汉模式” 延时懒汉可以看出代码并不着急所以懒汉模式型单例模式中的对象并不像饿汉模式中没有调用前就创建完成而是在第一调用方法实例时才被创建。 对比饿汉模式 优点会减少内存资源浪费。 缺点多线程环境并发运行可能会出现线程安全。 3.1 第一版
创建类MyObjectLazy.java代码如下
public class MyObjectLazy {//单例模式、懒汉模式private static MyObjectLazy myObjectLazy null;private static Object lock new Object();private MyObjectLazy(){};public static MyObjectLazy getMyObjectLazy(){if(myObjectLazy ! null){return myObjectLazy;}else{myObjectLazy new MyObjectLazy();}return myObjectLazy;}}创建线程类MyThreadLazy.java:
public class MyThreadLazy extends Thread{Overridepublic void run() {System.out.println(MyObjectLazy.getMyObjectLazy().hashCode());}
}创建运行类RunLazy.java:
public class RunLazy {//测试对象是不是同一个是的话就是安全的单例模式public static void main(String[] args) {MyThreadLazy t1 new MyThreadLazy();MyThreadLazy t2 new MyThreadLazy();MyThreadLazy t3 new MyThreadLazy();t1.start();t2.start();t3.start();}
}运行结果 结果不同所以并不是单例模式其中有问题造成线程不安全。
3.2 第二版
第一版生成不同对象所以造成非线程安全我们可以做出一点修改对代码加上锁。 修改后的MyObjectLazy.java: public static MyObjectLazy getMyObjectLazy(){synchronized (lock){if(myObjectLazy null){myObjectLazy new MyObjectLazy();}}return myObjectLazy;}运行结果 说明这个单例模式是正确实现了。
3.3 第三版
但是第二版又暴露一个问题上面加锁后相当于整个方法都加锁上面一个线程没有释放锁下一个线程将无法运行造成效率低下。 所以我们继续修改修改后的MyObjectLazy.java: public static MyObjectLazy getMyObjectLazy(){try{if(myObjectLazy null){Thread.sleep(1000);synchronized (lock){myObjectLazy new MyObjectLazy();}}}catch(InterruptedException e){e.printStackTrace();}return myObjectLazy;}运行结果 运行结果又不同了创建出了三个对象为什么这是因为虽然上了锁但是if已经判断只是new对象时串行。 虽然效率提高了但这并不是单例模式。
3.4 第四版
我们可以使用DCL双检查锁机制来实现进行两次if判断使线程安全。 修改后MyObjectLazy.java //再一次修改代码加锁只加一块并且应用DCL双检查机制来实现多线程环境下的延时加载单例模式保证线程安全public static MyObjectLazy getMyObjectLazy(){try{if(myObjectLazy null){Thread.sleep(1000);synchronized (lock){if(myObjectLazy null) {myObjectLazy new MyObjectLazy();}}}}catch(InterruptedException e){e.printStackTrace();}return myObjectLazy;}运行结果 使用双检查锁功能成功解决了懒汉模式遇到多线程的问题。DCL经常出现在此场景下我们要学会应用。