首页 未命名正文

linux编程_Java 单例模式详解

云返利网 未命名 2020-05-26 09:07:27 12 0

观点:
  Java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、挂号式单例三种。
  单例模式有一下特点:
  1、单例类只能有一个实例。
  2、单例类必须自己自己建立自己的唯一实例。
  3、单例类必须给所有其他工具提供这一实例。
  单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志工具、对话框、打印机、显卡的驱动程序工具常被设计成单例。这些应用都或多或少具有资源治理器的功效。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以制止两个打印作业同时输出到打印机中。每台计算机可以有若干通讯端口,系统应当集中治理这些通讯端口,以制止一个通讯端口同时被两个请求同时挪用。总之,选择单例模式就是为了制止不一致状态,制止政出多头。

首先看一个经典的单例实现。

public class Singleton {

    private static Singleton uniqueInstance = null;

 

    private Singleton() {

       // Exists only to defeat instantiation.

    }

 

    public static Singleton getInstance() {

       if (uniqueInstance == null) {

           uniqueInstance = new Singleton();

      }

       return uniqueInstance;

    }

    // Other methods...

}

Singleton通过将组织方式限定为private制止了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方式接见。(事实上,通过Java反射机制是能够实例化组织方式为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,临时掩耳盗铃地以为反射机制不存在。)

然则以上实现没有思量线程平安问题。所谓线程平安是指:若是你的代码所在的历程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。若是每次运行效果和单线程运行的效果是一样的,而且其他的变量的值也和预期的是一样的,就是线程平安的。或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行效果存在二义性,也就是说我们不用思量同步的问题。显然以上实现并不知足线程平安的要求,在并发环境下很可能泛起多个Singleton实例。

public class TestStream {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    //该类只能有一个实例
    private TestStream(){}    //私有无参组织方式
    //该类必须自行建立
    //有2种方式
    /*private static final TestStream ts=new TestStream();*/
    private static TestStream ts1=null;
    //这个类必须自动向整个系统提供这个实例工具
    public static TestStream getTest(){
        if(ts1==null){
            ts1=new TestStream();
        }
        return ts1;
    }
    public void getInfo(){
        System.out.println("output message "+name);
    }
}

----------------------------------------------

public class TestMain {
    public static void main(String [] args){
        TestStream s=TestStream.getTest();
        s.setName("张孝祥");
        System.out.println(s.getName());
        TestStream s1=TestStream.getTest();
        s1.setName("张孝祥");
        System.out.println(s1.getName());
        s.getInfo();
        s1.getInfo();
        if(s==s1){
            System.out.println("建立的是同一个实例");
        }else if(s!=s1){
            System.out.println("建立的不是同一个实例");
        }else{
            System.out.println("application error");
        }
    }
}

运行效果:
  张孝祥
  张孝祥
  output message 张孝祥
  output message 张孝祥
  建立的是同一个实例

结论:由效果可以得知单例模式为一个面向工具的应用程序提供了工具惟一的接见点,不管它实现何种功效,整个应用程序都市同享一个实例工具。

1.饿汉式单例类

//饿汉式单例类.在类初始化时,已经自行实例化
public class Singleton1 {
    //私有的默认组织子
    private Singleton1() {}
    //已经自行实例化
    private static final Singleton1 single = new Singleton1();
    //静态工厂方式
    public static Singleton1 getInstance() {
        return single;
    }
}

2.懒汉式单例类

//懒汉式单例类.在第一次挪用的时刻实例化
public class Singleton2 {
    //私有的默认组织子
    private Singleton2() {}
    //注重,这里没有final   
    private static Singleton2 single=null;
    //静态工厂方式
    public synchronized  static Singleton2 getInstance() {
        if (single == null) { 
            single = new Singleton2();
        } 
        return single;
    }
}

3.挂号式单例类

import java.util.HashMap;
import java.util.Map;
//挂号式单例类.
//类似Spring内里的方式,将类名注册,下次从内里直接获取。
public class Singleton3 {
    private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();
    static{
        Singleton3 single = new Singleton3();
        map.put(single.getClass().getName(), single);
    }
    //珍爱的默认组织子
    protected Singleton3(){}
    //静态工厂方式,返还此类惟一的实例
    public static Singleton3 getInstance(String name) {
        if(name == null) {
            name = Singleton3.class.getName();
            System.out.println("name == null"+"--->name="+name);
        }
        if(map.get(name) == null) {
            try {
                map.put(name, (Singleton3) Class.forName(name).newInstance());
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        return map.get(name);
    }
    //一个示意性的商业方式
    public String about() {   
        return "Hello, I am RegSingleton.";   
    }   
    public static void main(String[] args) {
        Singleton3 single3 = Singleton3.getInstance(null);
        System.out.println(single3.about());
    }
}

【关于云返利网】

云返利网是阿里云、腾讯云、华为云产品推广返利平台,在各个品牌云产品官网优惠活动之外,云返利网还提供返利。您可以无门槛获得阿里云、华为云、腾讯云所有产品返利,在官网下单后就可以领取,无论是自己用、公司用还是帮客户采购,您个人都可以获得返利。云返利网的目标是让返利更多、更快、更简单!详情咨询13121395187(微信同号)