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

优质的杭州网站优化短视频运营岗位职责和任职要求

优质的杭州网站优化,短视频运营岗位职责和任职要求,wordpress局域网自定义域名,短链接在线转换在项目中为了避免创建大量的对象,频繁出现gc的问题,单例设计模式闪亮登场。 一、饿汉式 1.1饿汉式 顾名思义就是我们比较饿,每次想吃的时候,都提前为我们创建好。其实我记了好久也没分清楚饿汉式和懒汉式的区别。这里给出我的一…

在项目中为了避免创建大量的对象,频繁出现gc的问题,单例设计模式闪亮登场。

一、饿汉式

1.1饿汉式

顾名思义就是我们比较饿,每次想吃的时候,都提前为我们创建好。其实我记了好久也没分清楚饿汉式和懒汉式的区别。这里给出我的一个记忆方法:懒汉式就是懒加载,什么是懒加载呢?就是我们需要的时候给创建对象就行,稍后介绍懒汉式的时候你会发现这个现象。

1.2饿汉式的特点

线程安全,但是如果一个项目需要创建大量的对象的时候,当项目运行的时候,会创建大量我们暂时用不到的对象。

1.3饿汉式代码
package singletonModel;
public class HungrySingleton {public static HungrySingleton instance=new HungrySingleton();private HungrySingleton(){}public static HungrySingleton getInstance(){return instance;}
}
1.4多线程下测试
package Test;
import singletonModel.DoubleLockSingleton;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;
public class SingletonTest {public static void main(String[] args) {// 使用AtomicReference来存储第一次获取到的LazySingleton实例AtomicReference<DoubleLockSingleton> singletonInstance = new AtomicReference<>();// 我们将启动大量线程来尝试突破单例的线程安全性ExecutorService executorService = Executors.newFixedThreadPool(100);// 用于发现多个实例创建的标志AtomicReference<Boolean> flag = new AtomicReference<>(false);// 提交多个任务到线程池,尝试并发地获取单例实例for (int i = 0; i < 100; i++) {executorService.submit(() -> {DoubleLockSingleton instance = DoubleLockSingleton.getInstance();// 如果原子引用为空,我们设置当前实例if (singletonInstance.get() == null) {singletonInstance.set(instance);} else if (singletonInstance.get() != instance) {// 如果原子引用中的实例与当前获取的实例不同,说明存在多个实例flag.set(true);System.out.println("Detected multiple instances!");}});}executorService.shutdown();// 等待所有任务完成while (!executorService.isTerminated()) {// 等待所有线程执行完毕}if (flag.get().equals(false)) {System.out.println("No multiple instances detected!");}}
}
1.5运行结果

在这里插入图片描述

通过实验证明,饿汉式在多线程环境下是线程安全的!

二、懒汉式

2.1懒汉式

顾名思义比较懒,叫我们的时候,我们在穿衣服去干活,即完成对象的创建的过程。

2.2懒汉式的特点

需要的时候,才为我们创建,能够避免在项目启动的时候,创建大量的无用对象,减少GC。缺点就是多线程操作下线程不安全!

2.3懒汉式代码
package singletonModel;
public class LazySingleton {private static LazySingleton lazyInstance;private LazySingleton(){}public static LazySingleton getInstance(){if(lazyInstance==null){lazyInstance= new LazySingleton();}return lazyInstance;}
}
2.4多线程下测试
package Test;
import singletonModel.LazySingleton;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;
public class SingletonTest {public static void main(String[] args) {// 使用AtomicReference来存储第一次获取到的LazySingleton实例AtomicReference<LazySingleton> singletonInstance = new AtomicReference<>();// 我们将启动大量线程来尝试突破单例的线程安全性ExecutorService executorService = Executors.newFixedThreadPool(100);// 用于发现多个实例创建的标志AtomicReference<Boolean> flag = new AtomicReference<>(false);// 提交多个任务到线程池,尝试并发地获取单例实例for (int i = 0; i < 100; i++) {executorService.submit(() -> {LazySingleton instance = LazySingleton.getInstance();// 如果原子引用为空,我们设置当前实例if (singletonInstance.get() == null) {singletonInstance.set(instance);} else if (singletonInstance.get() != instance) {// 如果原子引用中的实例与当前获取的实例不同,说明存在多个实例flag.set(true);System.out.println("Detected multiple instances!");}});}executorService.shutdown();// 等待所有任务完成while (!executorService.isTerminated()) {// 等待所有线程执行完毕}if (flag.get().equals(false)) {System.out.println("No multiple instances detected!");}}
}

上述代码需要多次测试,就能够测试出线程不安全的!

2.5测试结果

在这里插入图片描述
测试证明懒汉式在多线程操作下是线程不安全的!

2.6具体原因

具体的原因就是发生在下图的位置:即多线程环境下,不知线程哪个执行快慢,即存在两个线程A,B,线程A在进入if语句的时候,判断为空,然后完成对象的创建,但是对象的创建也需要一定时间,这个时候线程B也进入if判断,当前线程A还没有创建好,则判断为null,同时也完成对象的创建,这时候线程A,B创建的对象就不是同一个对象了。也就是线程不安全的了,即不满足原子性,可见性,有序性。
在这里插入图片描述

三、懒汉式方案修补方案一

为了保证线程安全,即满足原子性,可见性,有序性。我们首先想到的就是加锁!

由于getInstance方法为static修饰的方式,我们加了synchronized后,锁住的是当前的类,即加的类锁。即多线程操作该类的时候,只有1个线程操作成功!

3.1代码
package singletonModel;public class RLazySingleton {static RLazySingleton instance;private RLazySingleton(){}synchronized public static RLazySingleton getInstance(){if(instance==null){instance=new RLazySingleton();}return instance;}
}
3.2多线程测试代码
package Test;
import singletonModel.RLazySingleton;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;public class SingletonTest {public static void main(String[] args) {// 使用AtomicReference来存储第一次获取到的LazySingleton实例AtomicReference<RLazySingleton> singletonInstance = new AtomicReference<>();// 我们将启动大量线程来尝试突破单例的线程安全性ExecutorService executorService = Executors.newFixedThreadPool(100);// 用于发现多个实例创建的标志AtomicReference<Boolean> flag = new AtomicReference<>(false);// 提交多个任务到线程池,尝试并发地获取单例实例for (int i = 0; i < 100; i++) {executorService.submit(() -> {RLazySingleton instance = RLazySingleton.getInstance();// 如果原子引用为空,我们设置当前实例if (singletonInstance.get() == null) {singletonInstance.set(instance);} else if (singletonInstance.get() != instance) {// 如果原子引用中的实例与当前获取的实例不同,说明存在多个实例flag.set(true);System.out.println("Detected multiple instances!");}});}executorService.shutdown();// 等待所有任务完成while (!executorService.isTerminated()) {// 等待所有线程执行完毕}if (flag.get().equals(false)) {System.out.println("No multiple instances detected!");}}
}
3.3测试结果

在这里插入图片描述

实验结果证明:这种测试代码也是线程安全的!

3.4存在的问题

通过在getInstance()方法上添加synchronized关键字,可以强制每次只有一个线程能够访问方法,从而避免竞态条件。但这样做会影响性能,因为每次访问都需要进行同步。

四、双重锁检测方案

解决每次访问都需要进行同步的问题。

4.1代码
package singletonModel;
public class DoubleLockSingleton {private static DoubleLockSingleton instance;private DoubleLockSingleton(){}public  static  DoubleLockSingleton getInstance(){if(instance==null){synchronized (DoubleLockSingleton.class){if(instance==null){instance=new DoubleLockSingleton();}}}return instance;}
}
4.2测试代码
package Test;
import singletonModel.DoubleLockSingleton;
import singletonModel.RLazySingleton;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicReference;
public class SingletonTest {public static void main(String[] args) {// 使用AtomicReference来存储第一次获取到的LazySingleton实例AtomicReference<RLazySingleton> singletonInstance = new AtomicReference<>();// 我们将启动大量线程来尝试突破单例的线程安全性ExecutorService executorService = Executors.newFixedThreadPool(100);// 用于发现多个实例创建的标志AtomicReference<Boolean> flag = new AtomicReference<>(false);// 提交多个任务到线程池,尝试并发地获取单例实例for (int i = 0; i < 100; i++) {executorService.submit(() -> {RLazySingleton instance = RLazySingleton.getInstance();// 如果原子引用为空,我们设置当前实例if (singletonInstance.get() == null) {singletonInstance.set(instance);} else if (singletonInstance.get() != instance) {// 如果原子引用中的实例与当前获取的实例不同,说明存在多个实例flag.set(true);System.out.println("Detected multiple instances!");}});}executorService.shutdown();// 等待所有任务完成while (!executorService.isTerminated()) {// 等待所有线程执行完毕}if (flag.get().equals(false)) {System.out.println("No multiple instances detected!");}}
}
测试结果

实验结果也是线程安全的。
在这里插入图片描述

五、其他线程安全的写法

5.1静态内部类
public class StaticInnerClassSingleton {private static class LazyHolder {private static final StaticInnerClass INSTANCE = new StaticInnerClass();}private StaticInnerClass(){}public static StaticInnerClass getInstance(){return LazyHolder.INSTANCE;}
}
5.2枚举类
package singletonModel;public enum EnumSingleton {Instance;public void getInstance(){System.out.println("枚举类创建对象");}
}

六、总结

在Java中,使用枚举(enum)实现的单例模式是唯一能够抵御反射攻击的方式,因为枚举类型没有构造方法(在字节码层面是有私有构造器的,但这是由编译器自己添加的),所以无法通过反射来实例化枚举类型。
枚举攻击!!!

import java.lang.reflect.Constructor;public class ReflectionSingletonAttack {public static void main(String[] args) {Singleton instanceOne = Singleton.getInstance();Singleton instanceTwo = null;try {// 获取Singleton类的构造函数Constructor[] constructors = Singleton.class.getDeclaredConstructors();for (Constructor constructor : constructors) {// 设置构造函数的访问权限为可访问constructor.setAccessible(true);// 使用构造函数创建一个新的Singleton实例instanceTwo = (Singleton) constructor.newInstance();break;}} catch (Exception e) {e.printStackTrace();}// 打印两个实例的哈希码System.out.println("Instance 1 hash:" + instanceOne.hashCode());System.out.println("Instance 2 hash:" + instanceTwo.hashCode());}
}

枚举类单例模式抵挡枚举攻击

import java.lang.reflect.Constructor;public class EnumReflectionAttack {public static void main(String[] args) {EnumSingleton instanceOne = EnumSingleton.INSTANCE;EnumSingleton instanceTwo = null;try {Constructor[] constructors = EnumSingleton.class.getDeclaredConstructors();for (Constructor constructor : constructors) {constructor.setAccessible(true);instanceTwo = (EnumSingleton) constructor.newInstance();break;}} catch (Exception e) {e.printStackTrace();}System.out.println("Instance 1 hash:" + instanceOne.hashCode());System.out.println("Instance 2 hash:" + (instanceTwo != null ? instanceTwo.hashCode() : "instance creation failed"));}
}

在运行此代码时,您会收到类似以下的异常:

java.lang.IllegalArgumentException: Cannot reflectively create enum objects

因此,使用枚举的方式创建单例是安全的,它有效地防止了反射攻击以及解决了序列化问题。这也是为什么很多推荐使用枚举方式来实现单例模式的原因之一。

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

相关文章:

  • 网站主机免备案吗辽宁城建设计院有限公司网站
  • 漯河市源汇区网站建设安阳网站推广
  • 做网站工资怎么样自己的电脑做服务器 并建网站
  • 深圳网站seo优化公司仪征 做网站
  • 长沙外贸建站网站开发个人简介范文
  • 做网站快速排名软件网站百度搜不到
  • 怎么做网站筛选功能vancl凡客诚品官网
  • 上海建材网站建设页面设计结课总结
  • 用凡科建设网站郑州优之客网站建设
  • php网站开发课程美食网站建设毕业设计
  • 企业网站 phpcms网站建设分金手指排名二九
  • 校园网站建设的请示翔宇定制app下载
  • 仿制别人网站成都网站成都网站制作公司
  • 网站上一页下一页怎么做做爰视频免费观看网站
  • 外贸网站建设销售常用语湖南省住建云公共信息服务平台
  • 韩国网站never官网网站建设需申请注册域名
  • 巴彦淖尔专业做网站的网站对域名
  • 做装修的网站有哪些内容厦门做网站seo的
  • 站长工具seo综合查询怎么使用的网站收录代做
  • 推广农村特色产品建设网站方案分类信息免费发布网
  • 网站前台登录模板黄冈地区免费网站推广平台
  • 南京专门做网站苏州园区网站建设公司
  • 网站建设友情链接怎样交换新网站如何被快速收录
  • 电子商务网站运营织梦网站制作教程
  • 上海网站建设公司指南网站建设合作协议
  • 网站建设忽悠wordpress安装 第二步
  • 有免费做门户网站吗网络优化工程师前景如何
  • 求个网站这么难吗2021年广州市做民宿什么网站比较好
  • wordpress模块化建站网站维护中是怎么回事
  • 河南网站建设费用网站平台项目交接需要什么