• 单例模式


    单例模式(Singleton Pattern)是Java设计模式中常用的模式之一。

    单例模式是保证在程序的运行期,一个类的对象只有一个,构造方法只执行一次,得到的所有引用指向都是同一个对象。是一种最佳的创建对象的方式,它涉及到的只是一个单一的类,这个类负责创建自己的对象,同时确保只有单个对象被创建。包括提供一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。

    所以这也是被很多人人称之为懒汉模式或者饿汉模式的模式的原因。当然了,这两者是有区别的。

    在类加载的时候就执行实例化对象的操作。在调用特定的方法(getInstance)的时候,才去实例(调用的是构造方法)对象;

    关键代码:构造函数是私有的。

    注意:

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

    实现

    我们将创建一个 SingleObject 类。SingleObject 类有它的私有构造函数和本身的一个静态实例。

    SingleObject 类提供了一个静态方法,供外界获取它的静态实例。SingletonPatternDemo,我们的演示类使用 SingleObject 类来获取 SingleObject对象。

    类图如下:

    代码如下:

    创建一个 Singleton 类。

     1 public class SingleObject {
     2  
     3    //创建 SingleObject 的一个对象
     4    private static SingleObject instance = new SingleObject();
     5  
     6    //让构造函数为 private,这样该类就不会被实例化
     7    private SingleObject(){}
     8  
     9    //获取唯一可用的对象
    10    public static SingleObject getInstance(){
    11       return instance;
    12    }
    13  
    14    public void showMessage(){
    15       System.out.println("Hello World!");
    16    }
    17 }

    从 singleton 类获取唯一的对象。

     1 public class SingletonPatternDemo {
     2    public static void main(String[] args) {
     3  
     4       //不合法的构造函数
     5       //编译时错误:构造函数 SingleObject() 是不可见的
     6       //SingleObject object = new SingleObject();
     7  
     8       //获取唯一可用的对象
     9       SingleObject object = SingleObject.getInstance();
    10  
    11       //显示消息
    12       object.showMessage();
    13    }
    14 }

     单例模式的几种常见形式

    • 饿汉式:直接创建对象,不存在线程安全问题
      • 直接实例饿汉式(简介直观)
        • /**
           * 饿汉式
           * 直接创建实例 对象,不管你是否徐亚这个对象都会创建
           * 
           * 1)构造器私有化
           * 2)自行创建,并且静态变量保存
           * 3)向外提供这个实例
           * 4)强调这是一个实例,我们可以用final修改
           * @author dell
           *
           */
          public class Singleton1 {
              public final static Singleton1 instance = new Singleton1();
              
              private Singleton1() {
                  
              }
              
          }
      • 枚举式(最简洁)
        • package com.etc.Singleton;
          
          /**
           * 枚举类型,表示该类型的对象是有限的几个
           * 我们可以限定成一个,就成了单例
           * @author dell
           *
           */
          public enum Singleton2 {
              INSTANCE
          }
      • 静态代码饿汉式(适合复杂实例化)
        • public class Singleton3 {
              public static final Singleton3 INSTANCE;
              private String info;
              static {
                  try {
                      //这是我自己写的类加载配置文件
                      //里面有一个信息info=HuaChenYu
                      Properties pro = new Properties();
                      pro.load(Singleton3.class.getClassLoader().getResourceAsStream("single.properties"));
                      
                      INSTANCE = new Singleton3(pro.getProperty("info"));
                  } catch (IOException e) {
                      // TODO Auto-generated catch block
                      throw new RuntimeException();
                  }
              }
              
              private Singleton3(String info){
                  this.info = info;
              }
          
              public String getInfo() {
                  return info;
              }
          
              public void setInfo(String info) {
                  this.info = info;
              }
          
              @Override
              public String toString() {
                  return "Singleton3 [info=" + info + "]";
              }
              
          }
    • 懒汉式:延迟创建对象
      • 线程不安全(适用于单线程)
        • Singleton类
          /**
           * 懒汉式:
           * 延迟创建实力对象
           * 
           * 1)构造器私有化
           * 2)静态变量保存唯一实例
           * @author dell
           *
           */
          public class Singleton4 {
              private static Singleton4 INSTANCE;
              private Singleton4() {
                  
              }
              public static Singleton4 getInstance() {
                  if(INSTANCE == null) {
                      
                      try {
                          Thread.sleep(1000);
                      } catch (InterruptedException e) {
                          // TODO Auto-generated catch block
                          e.printStackTrace();
                      }
                      INSTANCE = new Singleton4();
                  }
                  return INSTANCE;
              }
          } 
        • Test测试类
          public class Test {
              public static void main(String[] args) throws Exception, ExecutionException {
                  // TODO Auto-generated method stub
                  Callable<Singleton4> c = new Callable<Singleton4>() {
          
                      @Override
                      public Singleton4 call() throws Exception {
                          // TODO Auto-generated method stub
                          return Singleton4.getInstance();
                      }
                  };
                  ExecutorService es = Executors.newFixedThreadPool(2);
                  Future<Singleton4> f1 = es.submit(c);
                  Future<Singleton4> f2 = es.submit(c);
                  
                  Singleton4 s1 = f1.get();
                  Singleton4 s2 = f2.get();
                  System.out.println(s1 == s2);
                  System.out.println(s1);
                  System.out.println(s2);
                  
                  es.shutdown();
              }
          }
          运行出来的结果有很多种不同,有运行结果是true的Hashcode一致的,也有不一样的。
                  
      • 线程安全(适用于多线程)
        • Singleton类
          public class Singleton5 {
          
              private static Singleton5 INSTANCE;
              private Singleton5() {
                  
              }
              public static Singleton5 getInstance() {
                  //为了提高性能添加一个判断条件
                  //在第一次实现的时候会因为多个线程同时抢的情况
                  //那在后面以及实例过后就不会再次执行了
                  if(INSTANCE == null) {
                  synchronized (Singleton5.class) {
                      if(INSTANCE == null) {
                          try {
                              Thread.sleep(1000);
                          } catch (InterruptedException e) {
                              // TODO Auto-generated catch block
                              e.printStackTrace();
                          }
                          INSTANCE = new Singleton5();
                      }
                  }
                  }
                  return INSTANCE;
              }
          }
        • Test测试类
          package com.etc.Singleton;
          
          import java.lang.reflect.Executable;
          import java.util.concurrent.Callable;
          import java.util.concurrent.ExecutionException;
          import java.util.concurrent.Executor;
          import java.util.concurrent.ExecutorService;
          import java.util.concurrent.Executors;
          import java.util.concurrent.Future;
          
          public class Test {
          
              public static void main(String[] args) throws Exception, ExecutionException {
                  // TODO Auto-generated method stub
                  Callable<Singleton5> c = new Callable<Singleton5>() {
          
                      @Override
                      public Singleton5 call() throws Exception {
                          // TODO Auto-generated method stub
                          return Singleton5.getInstance();
                      }
                  };
                  ExecutorService es = Executors.newFixedThreadPool(2);
                  Future<Singleton5> f1 = es.submit(c);
                  Future<Singleton5> f2 = es.submit(c);
                  
                  Singleton5 s1 = f1.get();
                  Singleton5 s2 = f2.get();
                  System.out.println(s1 == s2);
                  System.out.println(s1);
                  System.out.println(s2);
                  
                  es.shutdown();
              }
          
          }
          运行出来的结果就是true了
      • 静态内部类形式(适用于多线程)
        • /**
           * 在内部类被加载和初始化的时候,才创建INSTANCE实例对象.
           * 静态内部诶不会自动化随着外部类的加载和初始化而初始化,它是要单独去加载和初始化的。
           * 因为是在内部类加载和初始化时创建的,因此线程是安全的。
           */
          public class Singleton6 {
              private Singleton6() {
          
              }
              
              private static class Inner {
                  private static final Singleton6 INSTANCE = new Singleton6();
              }
          
              public static Singleton6 getInstance(){
                  return Inner.INSTANCE;
              }
          }
  • 相关阅读:
    STL的移动算法
    mysql insert和前台显示乱码
    垃圾回收算法简单介绍——JVM读书笔记&lt;二&gt;
    UVA
    读取系统执行状态的shell脚本
    【web 回车】web项目 注册或登录页面 回车登录无效,解决方案
    【maven】maven项目移除Maven Dependencies后如何再添加进去
    【web.xml】报错java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
    【shiro】关于shiro匹配URL的小用法
    【Sets】使用Google Guava工程中Sets工具包,实现集合的并集/交集/补集/差集
  • 原文地址:https://www.cnblogs.com/wudidamowang666/p/11144756.html
Copyright © 2020-2023  润新知