zoukankan      html  css  js  c++  java
  • 大话--单例模式

    定义

    保证在整个软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)。

    优点

    1、在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例。

    2、避免对资源的多重占用(比如写文件操作)。

    缺点

    没有接口,扩展困难。

    使用场景

    需要频繁的进行创建和销毁的对象、创建对象时耗时过多或耗费资源过多,但又经常用到的对象、工具类对象、频繁访问数据库或文件的对象(比如数据源、session工厂等)。

    tips

    • 1、单例类只能有一个实例。
    • 2、单例类必须自己创建自己的唯一实例。
    • 3、单例类必须给所有其他对象提供这一实例。

    关键代码

    构造器一定是私有的

    类图

    使用单例模式的源码

    java.lang.Runtime就使用了饿汉式的单例模式,因为Runtime一定会被使用,所以不会造成资源浪费。

    具体实现

    1.饿汉式(静态常量)

     1 package Singleton.Singletontest1;
     2 
     3 /**
     4  * @title: Singleton1
     5  * @Author yzhengy
     6  * @Date: 2020/7/30 20:22
     7  * @Question: 饿汉式(静态常量)
     8  */
     9 
    10 /*
    11  * @Date: 2020/7/30 20:23
    12  * 1.构造器私有化(防止new对象)
    13  * 2.类的内部创建对象
    14  * 3.向外暴露一个静态的公共方法(getInstance)
    15  * 优点:类装载时就完成了实例化,避免了多线程同步问题。
    16  * 缺点:没有达到懒加载效果,如果一直不使用这个实例,会造成内存的浪费。
    17  */
    18 public class Singleton1 {
    19     public static void main(String[] args) {
    20         Singleton instance = Singleton.getInstance();
    21         Singleton instance2 = Singleton.getInstance();
    22         System.out.println(instance == instance2);//true
    23         System.out.println(instance.hashCode()==instance2.hashCode());//true
    24     }
    25 }
    26 
    27 
    28 class Singleton{
    29     private Singleton(){}
    30 
    31     private final static Singleton instance = new Singleton();
    32 
    33     public static Singleton getInstance(){
    34         return instance;
    35     }
    36 }
    View Code

    2.饿汉式(静态代码块)

     1 package Singleton.Singletontest2;
     2 
     3 /**
     4  * @title: Singleton2
     5  * @Author yzhengy
     6  * @Date: 2020/7/30 20:34
     7  * @Question: 饿汉式(静态代码块)
     8  */
     9 
    10 /*
    11  * @Date: 2020/7/30 20:23
    12  * 1.构造器私有化(防止new对象)
    13  * 2.类的内部创建对象实例
    14  * 3.在静态代码块中创建单例对象
    15  * 4.向外暴露一个静态的公共方法(getInstance)
    16  * 优缺点:与饿汉式(静态常量)的优缺点相同
    17  */
    18 public class Singleton2 {
    19     public static void main(String[] args) {
    20         Singleton instance = Singleton.getInstance();
    21         Singleton instance2 = Singleton.getInstance();
    22         System.out.println(instance == instance2);//true
    23         System.out.println(instance.hashCode()==instance2.hashCode());//true
    24     }
    25 }
    26 
    27 
    28 class Singleton{
    29     private Singleton(){}
    30 
    31     private static Singleton instance;
    32 
    33     static{
    34         instance = new Singleton();
    35     }
    36 
    37     public static Singleton getInstance(){
    38         return instance;
    39     }
    40 }
    View Code

    3.懒汉式(线程不安全)

     1 package Singleton.Singletontest3;
     2 
     3 /**
     4  * @title: Singleton3
     5  * @Author yzhengy
     6  * @Date: 2020/7/31 8:35
     7  * @Question: 懒汉式(线程不安全)
     8  */
     9 
    10 /*
    11  * @Date: 2020/7/31 8:41
    12  * 起到了懒加载的效果,但是只能在单线程时使用。
    13  * 如果在多线程时使用,一个线程进入了if(instance==null)判断语句块,还未来得及往下执行,
    14  * 另一个线程也通过了这个判断语句,这时就会产生多个实例。就会破坏单例模式。
    15  */
    16 public class Singleton3 {
    17 
    18     public static void main(String[] args) {
    19         System.out.println("我是线程不安全的懒汉式!!!");
    20         Singleton instance = Singleton.getInstance();
    21         Singleton instance2 = Singleton.getInstance();
    22         System.out.println(instance == instance2);//true
    23         System.out.println(instance.hashCode()==instance2.hashCode());//true
    24     }
    25 
    26 }
    27 
    28 class Singleton{
    29     private Singleton(){}
    30 
    31     private static Singleton instance;
    32 
    33     //提供一个静态公有方法,当时用到该方法时,才会创建instance。(懒汉式的核心)
    34     public static Singleton getInstance(){
    35         if (instance == null)
    36             instance = new Singleton();
    37         return instance;
    38     }
    39 }
    View Code

    4.懒汉式(线程安全,同步方法)

     1 package Singleton.Singletontest4;
     2 
     3 /**
     4  * @title: Singleton4
     5  * @Author yzhengy
     6  * @Date: 2020/7/31 8:47
     7  * @Question: 懒汉式(线程安全,同步方法)
     8  */
     9 
    10 /*
    11  * @Date: 2020/7/31 8:47
    12  * 在线程不安全的懒汉式的基础上,直接加一个Synchronized锁,保证线程安全。
    13  * 缺点:每个线程想获取类的实例时,执行getInstance()方法都要进行同步,方法同步效率太低。
    14  *      其实这个方法执行一次实例化代码就可以了,后面想获取该类实例直接return就可以了。
    15  */
    16 public class Singleton4 {
    17 
    18     public static void main(String[] args) {
    19         System.out.println("我是线程安全的懒汉式!!!");
    20         Singleton instance = Singleton.getInstance();
    21         Singleton instance2 = Singleton.getInstance();
    22         System.out.println(instance == instance2);//true
    23         System.out.println(instance.hashCode()==instance2.hashCode());//true
    24     }
    25 
    26 }
    27 
    28 class Singleton{
    29     private Singleton(){}
    30 
    31     private static Singleton instance;
    32 
    33     //提供一个静态公有方法,当时用到该方法时,才会创建instance。(懒汉式的核心)
    34     public static synchronized Singleton getInstance(){
    35         if (instance == null)
    36             instance = new Singleton();
    37         return instance;
    38     }
    39 }
    View Code

    5.懒汉式(线程不安全,同步代码块)

     1 package Singleton.Singletontest5;
     2 
     3 /**
     4  * @title: Singleton5
     5  * @Author yzhengy
     6  * @Date: 2020/7/31 8:52
     7  * @Question: 懒汉式(线程不安全,同步代码块)
     8  */
     9 
    10 /*
    11  * @Date: 2020/7/31 8:55
    12  * 与懒汉式线程不安全会有同样的问题,可能在多线程环境下创建多个实例。
    13  */
    14 public class Singleton5 {
    15 
    16     public static void main(String[] args) {
    17         System.out.println("我是线程不安全的懒汉式2!!!");
    18         Singleton instance = Singleton.getInstance();
    19         Singleton instance2 = Singleton.getInstance();
    20         System.out.println(instance == instance2);//true
    21         System.out.println(instance.hashCode()==instance2.hashCode());//true
    22     }
    23 
    24 }
    25 
    26 class Singleton{
    27     private Singleton(){}
    28 
    29     private static Singleton instance;
    30 
    31     //提供一个静态公有方法,当时用到该方法时,才会创建instance。(懒汉式的核心)
    32     public static Singleton getInstance(){
    33         if (instance == null)
    34 
    35             synchronized (Singleton.class){
    36             instance = new Singleton();}
    37 
    38         return instance;
    39     }
    40 }
    View Code

    6.双重检查

     1 package Singleton.Singletontest6;
     2 
     3 /**
     4  * @title: Singleton6
     5  * @Author yzhengy
     6  * @Date: 2020/7/31 9:09
     7  * @Question: 双重检查--推荐使用
     8  */
     9 public class Singleton6 {
    10     public static void main(String[] args) {
    11         System.out.println("我是双重检查");
    12         Singleton instance = Singleton.getInstance();
    13         Singleton instance2 = Singleton.getInstance();
    14         System.out.println(instance == instance2);//true
    15         System.out.println(instance.hashCode()==instance2.hashCode());//true
    16     }
    17 }
    18 
    19 /*
    20  * @Date: 2020/7/31 9:16
    21  * 线程安全;延迟加载;效率较高;
    22  */
    23 class Singleton{
    24     private Singleton(){}
    25 
    26     private static volatile Singleton instance;
    27 
    28     public static Singleton getInstance(){
    29         if (instance == null){
    30             synchronized (Singleton.class){
    31                 if (instance == null)
    32                     instance = new Singleton();
    33             }
    34         }
    35         return instance;
    36     }
    37 }
    View Code

    7.静态内部类

     1 package Singleton.Singletontest7;
     2 
     3 /**
     4  * @title: Singleton7
     5  * @Author yzhengy
     6  * @Date: 2020/7/31 9:18
     7  * @Question: 静态内部类--推荐使用
     8  */
     9 public class Singleton7 {
    10     public static void main(String[] args) {
    11         System.out.println("我是静态内部类");
    12         Singleton instance = Singleton.getInstance();
    13         Singleton instance2 = Singleton.getInstance();
    14         System.out.println(instance == instance2);//true
    15         System.out.println(instance.hashCode()==instance2.hashCode());//true
    16     }
    17 }
    18 /*
    19  * @Date: 2020/7/31 9:20
    20  * 外部类被装载时,静态内部类并不会被装载。
    21  * 当调用getInstance时才会使静态内部类被装载,而且只会装载一次,装载时线程安全。
    22  * 优点:线程安全,利用静态内部类特点实现延迟加载,效率高。
    23  */
    24 class Singleton{
    25     private Singleton(){}
    26 
    27     //静态内部类,该类中有一个静态属性Singleton
    28     private static class SingletonInstance{
    29         private final static Singleton INSTANCE = new Singleton();
    30     }
    31 
    32     //提供一个静态的公有方法,直接返回SingletonInstance.INSTANCE
    33     public static Singleton getInstance(){
    34         return SingletonInstance.INSTANCE;
    35     }
    36 }
    View Code

    8.枚举

     1 package Singleton.Singletontest8;
     2 
     3 /**
     4  * @title: Singleton8
     5  * @Author yzhengy
     6  * @Date: 2020/7/31 9:30
     7  * @Question: 枚举--推荐使用
     8  */
     9 public class Singleton8 {
    10     public static void main(String[] args) {
    11         System.out.println("我是枚举");
    12         Singleton instance = Singleton.INSTANCE;
    13         Singleton instance2 = Singleton.INSTANCE;
    14         System.out.println(instance == instance2);//true
    15         System.out.println(instance.hashCode()==instance2.hashCode());//true
    16 
    17         instance.sayOK();
    18     }
    19 }
    20 /*
    21  * @Date: 2020/7/31 9:34
    22  * 使用枚举可以实现单例
    23  * 不仅可以避免多线程同步问题,还能防止反序列化重新创建新的对象。(其他方法则需要使用transient关键字)
    24  * 可以防止反射攻击。
    25  */
    26 enum Singleton{
    27     INSTANCE;
    28     public void sayOK(){
    29         System.out.println("ok");
    30     }
    31 }
    View Code
  • 相关阅读:
    你必须知道的关于大数据的七个概念
    SAS中的聚类分析方法总结
    SAS中的聚类分析方法总结
    数据分析的关键是制定聪明的决策
    数据分析的关键是制定聪明的决策
    想使用 MongoDB ,你应该了解这8个方面!
    利用crtmpserver搭建rtmp服务器
    【leetcode】Jump Game I, II 跳跃游戏一和二
    iOS中从零開始使用protobuf
    session.use_cookies有什么作用,
  • 原文地址:https://www.cnblogs.com/yzhengy/p/13408098.html
Copyright © 2011-2022 走看看