设计模式-单例模式-Java 总结+代码+解析

只看理论就是一看而过了,也不能真正理解,敲一下吧

  1. package pratice716;
  2. public class Singleton {
  3. /**
  4.  * 懒汉式-线程不安全
  5.  * 私有静态变量 uniqueInstance 被延迟实例化,这样做的好处是,如果没有用到该类,那么就不会实例化 uniqueInstance,从而节约资源。
  6.  * 多线程环境下是不安全的,如果多个线程能够同时进入 if (uniqueInstance == null) ,并且此时 uniqueInstance 为 null,那
  7.  * 么会有多个线程执行 uniqueInstance = new Singleton(); 语句,这将导致实例化多次 uniqueInstance。
  8.  */
  9.     private static Singleton uniqueInstance;
  10.     private Singleton(){
  11.         
  12.     }
  13.     public static Singleton getUniqueInstance(){
  14.         if(uniqueInstance == null){
  15.             uniqueInstance = new Singleton();
  16.         }
  17.         return uniqueInstance;
  18.     }
  19.     //2直接实例化,饿汉式,线程安全,不节约资源
  20.     private static Singleton uniqueInstance2 = new Singleton();
  21.     //2懒汉式-线程安全,对方法进行加锁.即使已被实例化,有线程进入,其他都等待,阻塞严重。不推荐
  22.     public static synchronized Singleton getUniqueInstance2(){
  23.         if(uniqueInstance == null){
  24.             uniqueInstance = new Singleton();
  25.         }
  26.         return uniqueInstance;
  27.     }
  28.     //3双重校验锁-线程安全:只需被实例化一次,加锁只对公有静态函数,先判断是否实例,木有实例才对实例化加锁
  29.     /*
  30.      * 只使用了一个 if 语句。在 uniqueInstance == null 的情况下,如果两个线程都执行了 if 语句,
  31.      * 那么两个线程都会进入 if 语句块内。虽然在 if 语句块内有加锁操作,但是两个线程都会执行 uniqueInstance = new Singleton();
  32.      * 这条语句,只是先后的问题,那么就会进行两次实例化。因此必须使用双重校验锁,也就是需要使用两个 if 语句:第一个 if
  33.      * 语句用来避免 uniqueInstance 已经被实例化之后的加锁操作,而第二个 if 语句进行了加锁,所以只能有一个线程进入,
  34.      * 就不会出现 uniqueInstance == null 时两个线程同时进行实例化操作。
  35.      */
  36.     private static Singleton uniqueInstance3;
  37.     public static Singleton getUniqueInstance3(){
  38. //使用双重if语句才能保证不能两次实例化
  39.         if(uniqueInstance == null){
  40.             synchronized(Singleton.class){
  41.                 if(uniqueInstance == null){
  42.                     uniqueInstance = new Singleton();
  43.                 }
  44.             }            
  45.         }
  46.         return uniqueInstance;
  47.     }
  48. //4禁止JVM的分配内存空间、初始化、指向分配的内存地址指令重排,保证多线程下正常运行.
  49. //4实例化采用volatile
  50.     private volatile static Singleton uniqueInstance4;
  51. /*
  52.  * 静态内部类
  53.  * 静态内部类只有调用对应方法才会被加载,实例也是一次,延迟初始化,线程安全
  54.  */
  55.     private static class SingletonH{
  56.         private static final Singleton IN = new Singleton();
  57.     }
  58.     public static Singleton getUniqueInstence(){
  59.         return SingletonH.IN;
  60.     }
  61. }

枚举:

  1. package pratice716;
  2. //枚举实现,enum的全称为 enumeration, 是 JDK 1.5中引入的新特性,存放在 java.lang包中。
  3. /*
  4. * 创建枚举类型要使用 enum 关键字,隐含了所创建的类型都是 java.lang.Enum 类的子类
  5. * (java.lang.Enum 是一个抽象类)。枚举类型符合通用模式 Class Enum<E extends Enum<E>>,
  6. * 而 E 表示枚举类型的名称。枚举类型的每一个值都将映射到 protected Enum(String name, int ordinal)
  7. * 构造函数中,在这里,每个值的名称都被转换成一个字符串,并且序数设置表示了此设置被创建的顺序。
  8. */    
  9. public enum Singleton1{
  10.     IN;
  11.     private String obj;
  12.     public String getobj(){
  13.         return obj;
  14.     }
  15.     public void setobj(String obj){
  16.         this.obj = obj;
  17.     }
  18.     public static void main(String args[])
  19.     {
  20.         //单例测试
  21.         Singleton1 first = Singleton1.IN;
  22.         first.setobj("first");
  23.         System.out.println("first: "+first);
  24.         Singleton1 second = Singleton1.IN;
  25.         second.setobj("second");
  26.         System.out.println("first: "+first);
  27.         System.out.println("second: "+second);
  28.         //反射获取实例
  29.         try {
  30.             Singleton[] enumConstants = Singleton.class.getEnumConstants();
  31.             for (Singleton enumConstant : enumConstants) {
  32.                 System.out.println(enumConstant.getObj());
  33.             }
  34.         } catch (Exception e) {
  35.             e.printStackTrace();
  36.         }
  37.     }
  38. /*
  39. * 该实现可以防止反射攻击。在其它实现中,通过 setAccessible() 方法可以将私有构造函数的访问级别设置为 public,
  40. * 然后调用构造函数从而实例化对象,如果要防止这种攻击,需要在构造函数中添加防止多次实例化的代码。该实现是由 JVM 保证只
  41. * 会实例化一次,因此不会出现上述的反射攻击。
  42. * 该实现在多次序列化和序列化之后,不会得到多个实例。而其它实现需要使用 transient 修饰所有字段,并且实现序列化和反序列化的方法。
  43. */
  44. }

扫码关注一起随时随地学习!!!就在洋葱攻城狮,更多精彩,等你来!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

洋葱ycy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值