listener java 单例模式_Java设计模式之--单例模式-使用懒汉模式创建

一、这是在单线程的情况下创建的

package com.sinosoft.test;

import javax.jnlp.SingleInstanceListener;

/**

*

*/

public class SingletonTest {

public static void main(String[] args) {

//可见这种方法就创建不了了

// LazySingleton lazySingleton=new LazySingleton();

LazySingleton lazySingleton = LazySingleton.getInstance();

}

}

//使用的时候才开始初始化,jvm运行的整个期间都只有一个实例

class LazySingleton {

private static LazySingleton instance;

public static LazySingleton getInstance() {

if (instance == null) {

instance = new LazySingleton();

}

return instance;

}

//将new 对象的构造方法屏蔽掉,不允许在外部进行多次创建

private LazySingleton() {

}

}

二、多线程场景下

package com.sinosoft.test;

import javax.jnlp.SingleInstanceListener;

import java.sql.Time;

import java.util.concurrent.TimeUnit;

/**

*

*/

public class SingletonTest {

public static void main(String[] args) {

//可见这种方法就创建不了了

// LazySingleton lazySingleton=new LazySingleton();

//下面我们验证一下在多线程的情况下看看会不会创建多个实例

new Thread(new Runnable() {

@Override

public void run() {

LazySingleton lazySingleton = LazySingleton.getInstance();

//通过打印他的内存地址来进行验证

System.out.println("============" + lazySingleton);

}

}).start();

new Thread(new Runnable() {

@Override

public void run() {

LazySingleton lazySingleton = LazySingleton.getInstance();

//通过打印他的内存地址来进行验证

System.out.println("============" + lazySingleton);

}

}).start();

}

}

//使用的时候才开始初始化,jvm运行的整个期间都只有一个实例

class LazySingleton {

private static LazySingleton instance;

public static LazySingleton getInstance() {

try {

if (instance == null) {

// 主要是模拟高并发场景下线程之间的调度

TimeUnit.MILLISECONDS.sleep(1200);

instance = new LazySingleton();

}

} catch (InterruptedException ex) {

ex.printStackTrace();

}

return instance;

}

//将new 对象的构造方法屏蔽掉,不允许在外部进行多次创建

private LazySingleton() {

}

}

运行结果:

我们可以看到创建了两个实例:

============com.sinosoft.test.LazySingleton@606232e4

============com.sinosoft.test.LazySingleton@7c60d4cb

出现这种情况的原因是:在同一时刻有两个线程在同时访问这个方法。怎样避免,我们可以将synchronized关键字,让同一时刻只能有一个线程进行访问。

//使用的时候才开始初始化,jvm运行的整个期间都只有一个实例

class LazySingleton {

private static LazySingleton instance;

public static synchronized LazySingleton getInstance() {

try {

if (instance == null) {

// 主要是模拟高并发场景下线程之间的调度

TimeUnit.MILLISECONDS.sleep(1200);

instance = new LazySingleton();

}

} catch (InterruptedException ex) {

ex.printStackTrace();

}

return instance;

}

//将new 对象的构造方法屏蔽掉,不允许在外部进行多次创建

private LazySingleton() {

}

运行结果:

============com.sinosoft.test.LazySingleton@606232e4

============com.sinosoft.test.LazySingleton@606232e4

其实上面这种加锁的方式是比较重的一种方法,固定死了一次就只能有一个线程进行访问,不利于高并发场景。

解决这种问题,我们可以使用双重校验(或者叫双重锁)

//使用的时候才开始初始化,jvm运行的整个期间都只有一个实例

class LazySingleton {

private static LazySingleton instance;

public static LazySingleton getInstance() {

try {

if (instance == null) {

// 主要是模拟高并发场景下线程之间的调度

synchronized (LazySingleton.class) {

if (instance == null) {

instance = new LazySingleton();

}

}

}

} catch (Exception ex) {

ex.printStackTrace();

}

return instance;

}

//将new 对象的构造方法屏蔽掉,不允许在外部进行多次创建

private LazySingleton() {

}

运行结果:

============com.sinosoft.test.LazySingleton@52a17671

============com.sinosoft.test.LazySingleton@52a17671

当然为了防止jvm指令重排序,我们加上volatile关键字进行修饰:

private static volatile LazySingleton instance;

三、使用静态内部类进行单例模式的创建,这也是懒汉模式的一种实现方式

package com.sinosoft.test;

/**

* 这是通过静态内的方式实现单例模式,也是懒加载的一种实现方式

*/

public class InnerClassSingleton {

static class InnerClass{

private static InnerClassSingleton instance=new InnerClassSingleton();

}

//这是提供给外部进行访问和创建单例的方法

public static InnerClassSingleton getInstance(){

return InnerClass.instance;

}

private InnerClassSingleton(){

}

}

接下来,我们通过反射机制来破坏单例类的创建

package com.sinosoft.test;

import java.lang.reflect.Constructor;

/**

* 接下来,我们对我们创建的单例类通过反射的机制进行破坏,也就是说创建多个实例

*/

public class Anti {

public static void main(String[] args) {

try{

//使用反射的机制获取实例

Constructor declaredConstructor = InnerClassSingleton.class.getDeclaredConstructor();

declaredConstructor.setAccessible(true);

InnerClassSingleton innerClassSingleton = declaredConstructor.newInstance();

//使用静态内部类的方式获取实例

InnerClassSingleton instance = InnerClassSingleton.getInstance();

System.out.println(innerClassSingleton==instance);

}catch (Exception e){

e.printStackTrace();

}

}

}

运行结果:

false

我们能够发现,我们创建了两个不同的实例,这种情况下,我们应该怎样解决呢,答案很简单。

a2980a681596d1af0de9d3c6a75e08fd.png

再次运行程序:

af9d67ba6103879f8beaf814b8f1f50e.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值