当前位置: 首页 > news >正文

网站建设定做淘客优惠券推广网站怎么做

网站建设定做,淘客优惠券推广网站怎么做,南昌做网站的公司哪个比较好的,青海项目信息网单例模式 单例模式使用场景 ​ 什么是单例模式?保障一个类只能有一个对象(实例)的代码开发模式就叫单例模式 ​ 什么时候使用? 工具类!(一种做法,所有的方法都是static,还有一种单…

单例模式

单例模式使用场景

​ 什么是单例模式?保障一个类只能有一个对象(实例)的代码开发模式就叫单例模式
​ 什么时候使用? 工具类!(一种做法,所有的方法都是static,还有一种单例模式让工具类只有一个实例) 某类工厂(SqlSessionFactory)

实现方式

1. 饿汉

/*** 饿汉模式(迫切加载)*/
public class Singleton01 {//构造私有化private Singleton01(){}//2 创建一个private对象private static final Singleton01 INSTANCE = new Singleton01();//这个地方就体现饿汉,一来就创建对象给他//3 提供一个static方法来获取你的这个单实例对象public static Singleton01 newInstance(){return INSTANCE;}
}

测试代码

public class MyTest {public static void main(String[] args) {Singleton01 singleton01 = Singleton01.newInstance();Singleton01 singleton02 = Singleton01.newInstance();System.out.println(singleton01.equals(singleton02));}
}

输出为true说明两个对象是相同的

2. 懒汉(懒汉太懒了,要用的时候才能创建。)

/*** 懒汉模式(懒加载) 单线程*/
public class Singleton02 {private Singleton02() {}//2 创建一个private对象private static Singleton02 INSTANCE;//3 提供一个static方法来获取你的这个单实例对象 只适合在单线程中public static Singleton02 newInstance() {if(INSTANCE == null){INSTANCE = new Singleton02()}return INSTANCE;}
}

测试代码

public class MyTest {public static void main(String[] args) {Singleton02 singleton03 = Singleton02.newInstance();Singleton02 singleton04 = Singleton04.newInstance();System.out.println(singleton03.equals(singleton04));}
}

输出为true说明两个对象是相同的
懒汉模式 只要不调用newInstance()方法 INSTANCE就一直为空 只用调用了才会创建

测试代码(如果多线程 就不是单例了)

public class MyTest {public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(() -> Singleton02.newInstance()).start();}}
}

运行结果
在这里插入图片描述

说明有不同的线程都调用到了构造方法
解决方法:加锁
1.方法上加锁
public static synchronized Singleton02 newInstance()
缺点:锁住整个方法 里面还有业务逻辑 效率降低很多
2.synchronized代码块

/*** 懒汉模式(懒加载)*/
public class Singleton02 {private Singleton02() {}//2 创建一个private对象private static Singleton02 INSTANCE;//3 提供一个static方法来获取你的这个单实例对象//方案1:方法锁,里面还有业务逻辑//public static synchronized  Singleton02 newInstance(){public static Singleton02 newInstance() {//方案2:锁代码块//synchronized (Singleton02.class){ // 100个线程哪怕有一个已经创建了也要排队if (INSTANCE == null) {//多线程来了? T1 T2synchronized (Singleton02.class) {if (INSTANCE == null) {INSTANCE = new Singleton02();}}}//}//此处有10W行代码....return INSTANCE;}//普通方法public String getConnection() {return "I am connection!";}
}

在这里插入图片描述

只会有一个线程调用到构造方法

写到这里是不是觉得单例模式已经可以了?
但是这个代码也不是绝对安全的,不绝对是单例 利用反射去创建类的对象可以将单例进行破坏 写个测试代码

public class MyTest {
public static void main(String[] args) throws Exception{//正常获取Singleton02 instance = Singleton02.newInstance();//通过反射获取Class<? extends Singleton02> aClass = instance.getClass();//注意:构造方法是私有的Constructor<? extends Singleton02> declaredConstructor = aClass.getDeclaredConstructor(null);declaredConstructor.setAccessible(true);Singleton02 instance02 = declaredConstructor.newInstance();System.out.println(instance);System.out.println(instance02);}
}

在这里插入图片描述

生成了两个对象,说明已经通过反射将单例破坏掉了

修改代码

/*** 懒汉模式(懒加载)*/
public class Singleton02 {private Singleton02() {synchronized (Singleton02.class) {if (INSTANCE != null){throw new RuntimeException("防止反射破坏单例");}}}//2 创建一个private对象private static Singleton02 INSTANCE;//3 提供一个static方法来获取你的这个单实例对象//方案1:方法锁,里面还有业务逻辑//public static synchronized  Singleton02 newInstance(){public static Singleton02 newInstance() {//方案2:锁代码块//synchronized (Singleton02.class){ // 100个线程哪怕有一个已经创建了也要排队if (INSTANCE == null) {//多线程来了? T1 T2synchronized (Singleton02.class) {if (INSTANCE == null) {INSTANCE = new Singleton02();}}}//}//此处有10W行代码....return INSTANCE;}//普通方法public String getConnection() {return "I am connection!";}
}

在这里插入图片描述

那到这一步反射就不能搞破坏了吗?
答案是可以的 为什么?
因为第一次创建的时候使用的是正常的方式肯定会调用构造方法
将第一个打印放到反射创建之前就会打印出第一个的对象 第二次通过反射再拿一个对象就不行 如果我两次都使用反射来获取对象

public class MyTest {
public static void main(String[] args) throws Exception{
Class<? extends Singleton02> aClass = Singleton02.class;//注意:构造方法是私有的Constructor<? extends Singleton02> declaredConstructor = aClass.getDeclaredConstructor(null);declaredConstructor.setAccessible(true);Singleton02 instance01 = declaredConstructor.newInstance();Singleton02 instance02 = declaredConstructor.newInstance();System.out.println(instance01);System.out.println(instance02);}
}

在这里插入图片描述

ok 单例又被破坏
还有没有其他方法?
不管是反射还是正常都会调用构造方法 那就先搞一个字段flag来进行校验

package org.jhy._01singleton;/*** 懒汉模式(懒加载)*/
public class Singleton02 {private static Boolean flag = false;private Singleton02() {
//        synchronized (Singleton02.class) {
//            if (INSTANCE != null){
//                throw new RuntimeException("防止反射破坏单例");
//            }
//        }if (flag == false) {flag = true;} else {throw new RuntimeException("防止反射破坏单例");}}//2 创建一个private对象private static Singleton02 INSTANCE;//3 提供一个static方法来获取你的这个单实例对象//方案1:方法锁,里面还有业务逻辑//public static synchronized  Singleton02 newInstance(){public static Singleton02 newInstance() {//方案2:锁代码块//synchronized (Singleton02.class){ // 100个线程哪怕有一个已经创建了也要排队if (INSTANCE == null) {//多线程来了? T1 T2synchronized (Singleton02.class) {if (INSTANCE == null) {INSTANCE = new Singleton02();}}}//}//此处有10W行代码....return INSTANCE;}//普通方法public String getConnection() {return "I am connection!";}
}
public class MyTest {
public static void main(String[] args) throws Exception{
//通过反射获取Class<? extends Singleton02> aClass = Singleton02.class;//注意:构造方法是私有的Constructor<? extends Singleton02> declaredConstructor = aClass.getDeclaredConstructor(null);declaredConstructor.setAccessible(true);Singleton02 instance01 = declaredConstructor.newInstance();//获取字段名Field flag = aClass.getDeclaredField("flag");flag.setAccessible(true);//获取之后复位 认为又是第一次flag.set(instance01,false);Singleton02 instance02 = declaredConstructor.newInstance();System.out.println(instance01);System.out.println(instance02);}
}

在这里插入图片描述

ok,单例又被破坏了
那么反射真的就无所不能了吗???

让我们来看看newInstance()这个方法的源码
在这里插入图片描述

不能通过反射创建枚举的对象,所以用枚举就能防止反射破坏单例

public enum Singleton03 {INSTANCE;public void testMethod(){System.out.println("执行了单例类的方法");}
}// Test.java
class Test {public static void main(String[] args) {//演示如何使用枚举写法的单例类Singleton03.INSTANCE.testMethod();System.out.println(Singleton03.INSTANCE);Singleton03 instance01 = Singleton03.INSTANCE;Singleton03 instance02 = Singleton03.INSTANCE;System.out.println(instance01.equals(instance02));}
}

结果显然为true 而且枚举类里面就不能用反射的方法 枚举里面只有一个实例那就是单例

http://www.yayakq.cn/news/214718/

相关文章:

  • 怎么做网站流量统计分析商务网站大全
  • 科技类网站3d做网站
  • 深圳手机网站定制开发免费注册邮箱帐号
  • 做局域网网站重庆网站设计总部
  • 网盘做电子书下载网站站长工具永久更新
  • 免费做ppt网站建程网官网
  • 福田公司网站建设北京seo业务员
  • 建设cpa网站需要什么哪个网站做的最好
  • 自己做的网站怎么才有用户访问福州建设公司名单
  • 注册网站免费注册ins毕业答辩ppt 网站开发
  • 三河市城乡建设局网站wordpress 首页调用页面标题
  • 重庆靓号网站建设在线写作网站
  • 深圳建设银行网站wordpress登入后台没反应
  • asp源码-漂亮企业源码大气公司网站模版wordpress替换主题数据库
  • 网站 展示展示网站模板下载
  • 网站导航页面设计单页营销型网站模板
  • 鞍山市城乡建设局网站北京有哪些软件公司在招聘
  • 做生鲜的网站拼多多网站
  • 照片展示网站百度收录入口在哪里查询
  • 企业网站明细费用网站数据每隔几秒切换怎么做的
  • 哪些行业做网站的多陕西省建设厅网站查询
  • 网站幻灯片尺寸设置免费平面设计模板网站
  • 连云港做网站建设vs2010网站开发 SQL
  • 做外贸最适合的网站系统软件下载网站模板
  • 网站优化的目的wordpress 大内存
  • 苏州网站建设seo开个小网站要怎么做
  • 如何做网站安全扫描有奖竞猜网站建设
  • 毕节建设网站平面设计做兼职网站
  • 金属加工网站建设淘宝网网页设计作业
  • 企业二级域名自助建站平台网站开发使用的技术有哪些