深度解析单例模式(单例模式总结)

  本篇文章为你整理了深度解析单例模式(单例模式总结)的详细内容,包含有深度解析单例模式有哪些 单例模式总结 单例模式示例 单例模式详解 深度解析单例模式,希望能帮助你了解 深度解析单例模式。

   private final static Hungry hungry = new Hungry();

   public static Hungry getInstance(){

   return hungry;

   public static void main(String[] args) {

   . Hungry.getInstance();

  

 

 

  会浪费内存,执行代码,其4个对象已经被创建,浪费空间。

  懒汉式单例

  

package com.cz.single;

 

   * @author 卓亦苇

   * @version 1.0

   * 2023/3/11 21:35

  public class LazyMan {

   private LazyMan(){

   System.out.println(Thread.currentThread().getName()+" OK");

   private volatile static LazyMan lazyMan;

   public static LazyMan getLazyMan(){

   if ((lazyMan==null)){

   synchronized (LazyMan.class){

   if (lazyMan==null){

   lazyMan = new LazyMan();

   return lazyMan;

   public static void main(String[] args) {

   for (int i = 0; i i++) {

   new Thread(()- {

   LazyMan.getLazyMan();

   }).start();

  

 

  懒汉式为使用该对象才创建新对象,但是初始代码有问题,单线程初始没有问题,多线程会造成,非单例。

  解决办法,首先加锁,先判断对象是否为空,如果为空则将class对象进行上锁,然后需再判断,锁是否为空,如果为空再创建新对象。

  同步代码块简单来说就是将一段代码用一把锁给锁起来, 只有获得了这把锁的线程才访问, 并且同一时刻, 只有一个线程能持有这把锁, 这样就保证了同一时刻只有一个线程能执行被锁住的代码。第二层,是因为使用同步代码块才加上的,有的可能过了第一个if,没到同步代码块

  为双层检测的懒汉式单例,也称DCL懒汉式

  第二个问题

  

lazyMan = new LazyMan();

 

  

 

  代码为非原子性操作

  创建新对象的底层操作分为3步

  1.分配内存空间
 

  2、执行构造方法,初始化对象
 

  3、把这个对象指向这个空间
 

  但如果不是原子操作,那132的状况式可能发现的,如果在A还没完成构造是,线程B进来,则不会执行if语句,发生错误

  让lazyMan加上volatile参数

  反射会破坏单例模式

  

public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {

 

  // for (int i = 0; i i++) {

  // new Thread(()- {

  // LazyMan.getLazyMan();

  // }).start();

   LazyMan lazyMan1 = LazyMan.getLazyMan();

   //获得空参构造器

   Constructor LazyMan declaredConstructor = LazyMan.class.getDeclaredConstructor(null);

   //反射的setAccessible(true)参数,无视私有构造器

   declaredConstructor.setAccessible(true);

   //通过反射建造对象

   LazyMan lazyMan2 = declaredConstructor.newInstance();

   System.out.println(lazyMan1);

   System.out.println(lazyMan2);

  

 

  解决办法,在无参构造器添加异常

  

private LazyMan(){

 

   synchronized (LazyMan.class){

   if (lazyMan!=null){

   throw new RuntimeException("不要试图反射破坏");

   System.out.println(Thread.currentThread().getName()+" OK");

  

 

  但依然存在问题, if (lazyMan!=null)为非原子性操作,依然存在两个反射对象导致出现非单例的状况

  

//可以采用红绿灯解决,定义一个密钥

 

  private static boolean key = false;

  private LazyMan(){

   synchronized (LazyMan.class){

   if (key==false){

   key=true;

   }else {

   throw new RuntimeException("不要试图反射破坏");

   System.out.println(Thread.currentThread().getName()+" OK");

  

 

  但是如果仍然用反射破环,假设获取到了密钥的情况

  

//通过反射修改静态参数

 

  Field key1 = LazyMan.class.getDeclaredField("key");

  key1.setAccessible(true);

  //获得空参构造器

  Constructor LazyMan declaredConstructor = LazyMan.class.getDeclaredConstructor(null);

  //反射的setAccessible(true)参数,无视私有构造器

  declaredConstructor.setAccessible(true);

  //通过反射建造对象

  LazyMan lazyMan1 = declaredConstructor.newInstance();

  //修改对象的密钥参数

  key1.set(lazyMan1,false);

  LazyMan lazyMan2 = declaredConstructor.newInstance();

  System.out.println(lazyMan1);

  System.out.println(lazyMan2);

  

 

  单例仍然会被破坏

  真实有效的方式枚举

  

package com.cz.single;

 

  import java.lang.reflect.Constructor;

  import java.lang.reflect.InvocationTargetException;

   * @author 卓亦苇

   * @version 1.0

   * 2023/3/14 16:26

  public enum EnumSingle {

   INSTANCE;

   public EnumSingle getInstance(){

   return INSTANCE;

  class Test{

   public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {

   EnumSingle instance1 = EnumSingle.INSTANCE;

   //EnumSingle instance2 = EnumSingle.INSTANCE;

   Constructor EnumSingle declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);

   declaredConstructor.setAccessible(true);

   EnumSingle instance2 = declaredConstructor.newInstance();

   System.out.println(instance1);

   System.out.println(instance2);

  

 

  至此才得以真正解决

  以上就是深度解析单例模式(单例模式总结)的详细内容,想要了解更多 深度解析单例模式的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: