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

Dw制作个人网站网站建设建设公司资质要求

Dw制作个人网站,网站建设建设公司资质要求,陕西网站建设咨询,微网站与微信的关系在项目中为了避免创建大量的对象#xff0c;频繁出现gc的问题#xff0c;单例设计模式闪亮登场。 一、饿汉式 1.1饿汉式 顾名思义就是我们比较饿#xff0c;每次想吃的时候#xff0c;都提前为我们创建好。其实我记了好久也没分清楚饿汉式和懒汉式的区别。这里给出我的一…在项目中为了避免创建大量的对象频繁出现gc的问题单例设计模式闪亮登场。 一、饿汉式 1.1饿汉式 顾名思义就是我们比较饿每次想吃的时候都提前为我们创建好。其实我记了好久也没分清楚饿汉式和懒汉式的区别。这里给出我的一个记忆方法懒汉式就是懒加载什么是懒加载呢就是我们需要的时候给创建对象就行稍后介绍懒汉式的时候你会发现这个现象。 1.2饿汉式的特点 线程安全但是如果一个项目需要创建大量的对象的时候当项目运行的时候会创建大量我们暂时用不到的对象。 1.3饿汉式代码 package singletonModel; public class HungrySingleton {public static HungrySingleton instancenew 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实例AtomicReferenceDoubleLockSingleton singletonInstance new AtomicReference();// 我们将启动大量线程来尝试突破单例的线程安全性ExecutorService executorService Executors.newFixedThreadPool(100);// 用于发现多个实例创建的标志AtomicReferenceBoolean 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(lazyInstancenull){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实例AtomicReferenceLazySingleton singletonInstance new AtomicReference();// 我们将启动大量线程来尝试突破单例的线程安全性ExecutorService executorService Executors.newFixedThreadPool(100);// 用于发现多个实例创建的标志AtomicReferenceBoolean 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具体原因 具体的原因就是发生在下图的位置即多线程环境下不知线程哪个执行快慢即存在两个线程AB线程A在进入if语句的时候判断为空然后完成对象的创建但是对象的创建也需要一定时间这个时候线程B也进入if判断当前线程A还没有创建好则判断为null同时也完成对象的创建这时候线程AB创建的对象就不是同一个对象了。也就是线程不安全的了即不满足原子性可见性有序性。 三、懒汉式方案修补方案一 为了保证线程安全即满足原子性可见性有序性。我们首先想到的就是加锁 由于getInstance方法为static修饰的方式我们加了synchronized后锁住的是当前的类即加的类锁。即多线程操作该类的时候只有1个线程操作成功 3.1代码 package singletonModel;public class RLazySingleton {static RLazySingleton instance;private RLazySingleton(){}synchronized public static RLazySingleton getInstance(){if(instancenull){instancenew 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实例AtomicReferenceRLazySingleton singletonInstance new AtomicReference();// 我们将启动大量线程来尝试突破单例的线程安全性ExecutorService executorService Executors.newFixedThreadPool(100);// 用于发现多个实例创建的标志AtomicReferenceBoolean 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(instancenull){synchronized (DoubleLockSingleton.class){if(instancenull){instancenew 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实例AtomicReferenceRLazySingleton singletonInstance new AtomicReference();// 我们将启动大量线程来尝试突破单例的线程安全性ExecutorService executorService Executors.newFixedThreadPool(100);// 用于发现多个实例创建的标志AtomicReferenceBoolean 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.hkea.cn/news/14390129/

相关文章:

  • 广州网站开发 英诺科技外贸网站建设 双语网站建设
  • 新邱建设网站做汽车租赁主要的网站
  • 做网站什么前端框架方便国内机械加工企业排名
  • 深网站建设建设单位企业锁登陆网站
  • 聊城网站建设设计实力公司wordpress做学校网站
  • 服务器部署php网站网站的网站制作
  • 建立网站需要多少人公司内部网站维护
  • 怎么做样网站需要网站开发
  • 如何选择合适的建站公司爱网站免费一站二站
  • 怎么建立网站站点商家自己做的商品信息查询网站
  • 宣传网站开发龙岗网站设计机构
  • 网站建设技术开发wordpress网页效果
  • 主流网站关键词排名企业型网站建设
  • 网站做兼容需要多少钱wordpress中的类
  • 算命网站搭建网站风格特点
  • 宁波网络推广平台哪里有北京seo优化
  • 网站栏目结构图模板网站制作成app
  • 建设银行网站维护买高端品牌网站
  • 东莞网站优化流程自学设计的网站有哪些
  • 网站租用服务器wordpress单页
  • 企业网站内页建筑网官网下载
  • 企业微信网站建设方案模板下载自己弄个网站
  • 网站设计公司费用公司关键词seo
  • 录音录像手表网站重庆模板网站建站
  • 建设一个行业性的网站价格网络管理系统提供网络管理需要的大量运算和记忆资源
  • 代运网站asp网站开发软件
  • 如何做网站需求表格清单学做的网站基础蛋糕
  • 怎么用源码做网站网站建设管理工作总结报告
  • 网站收录的页面被k出来潮州网站推广教程
  • 公司网站建设找哪家星子网易云