1、懒汉式定义:
懒汉式设计模式:比较懒,在类创建时不创建对象,而是以延迟加载的方式,当需要使用时才创建。
2、懒汉式的优缺点:
3、懒汉式的基础创建方式:
package com.zxl.design.zxl.design.pattern.singleton;
/**
* Created by Administrator on 2019/6/16.
* 懒汉式是指初始化时是不创建的,在运行时延迟加载。
* 单线程时没问题,但是多线程时会出现问题
*
*/
public class LazySingleton {
/**
* 初级懒汉式单例设计模式
* 线程不安全的,单线程时不会出问题,但是多线程时会出问题
* 假设两个线程同时运行,第一个线程在判断完if (lazySingleton == null)为true,
* 进入到方法内,但是还未执行创建对象或者还未执行完创建对象的步骤时,
* 此时lazySingleton 还是null,第二个线程刚好走到判断是否为null时,则判断为null,
* 之后线程二也会进入该方法。这样两个线程都进入,则都会正常创建对象, 造成创建两个对象。
*即使最后lazySingleton返回的对象一样(因为lazySingleton被赋值两次,后一次将前一次覆盖)
* 也同样是存在安全隐患。
* */
private static LazySingleton lazySingleton = null;
private LazySingleton(){
}
public static LazySingleton getInstance(){
if (lazySingleton == null){
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
1)该类的基本使用方案:
package com.zxl.design.zxl.design.pattern.singleton;
/**
* Created by Administrator on 2019/6/16.
*/
public class Test {
public static void main(String[] args) {
//该方案为单例模式,证明目前没有问题,
//因为LazySingleton的构造方法私有,外部无法调用,所以
//只能通过提供的公共访问方法构建。注:大家习惯用getInstance()这个方法名
//但并不是必须的。建议可读性好,一般用该方法名
//该测试方案通过debug的方式可以说明,类加载时是没有创建对象的,
//等到使用该类时,才创建了对象,也就是所说的延迟加载。
LazySingleton lazySingleton = LazySingleton.getInstance();
System.out.print("program end");
}
}
2)如何验证该方案存在问题呢?
我们要创建一个多线程的环境,通过debug方式手动控制其运行节奏,模拟该可能性。
首先创建一个线程类(后面还会用到),在其中通过不安全的懒汉式创建一个对象。并打印线程的名字和它的值
然后测试类中创建两个线程,并开启。具体如下:
package com.zxl.design.zxl.design.pattern.singleton;
import java.net.SocketPermission;
/**
* Created by Administrator on 2019/6/23.
*/
public class T implements Runnable {
public void run() {
LazySingleton lazySingleton = LazySingleton.getInstance();
System.out.println(Thread.currentThread().getName() +" "+ lazySingleton);
}
}
package com.zxl.design.zxl.design.pattern.singleton;
/**
* Created by Administrator on 2019/6/16.
*/
public class Test {
public static void main(String[] args) {
// //该方案为单例模式,证明目前没有问题,
// //因为LazySingleton的构造方法私有,外部无法调用,所以
// //只能通过提供的公共访问方法构建。注:大家习惯用getInstance()这个方法名
// //但并不是必须的。建议可读性好,一般用该方法名
// //该测试方案通过debug的方式可以说明,类加载时是没有创建对象的,
// //等到使用该类时,才创建了对象,也就是所说的延迟加载。
// LazySingleton lazySingleton = LazySingleton.getInstance();
// System.out.print("program end");
Thread t1 = new Thread(new T());
Thread t2 = new Thread(new T());
t1.start();
t2.start();
System.out.print("program end");
}
}
在如上不加干预的情况下,看最终运行的结果,好像是没问题的,但是在多线程中呢?
"D:\Program Files\Java\jdk1.8.0_102\bin\java" -agentlib:jdwp=tran