实现单例设计模式的多种方式

Singleton:在Java中即指单例设计模式,它是软件开发中最常用的设计模式之一。
单例设计模式,即即某个类在整个系统中只能有一个实例对象可被获取和使用的代码模式。
例如:代表JVM运行环境的Runtime类

要点:
- 某个类只能有一个实例:构造器私有化
- 它必须能够创建该类实例:使用该类的静态变量来保存这个唯一的实例。
- 它必须能返回该实例:通过get方法返回该实例或直接暴露给外部.

一、 饿汉式:直接创建对象,不存在线程安全问题

1.1、 直接实例化饿汉式(简洁直观)
/*
 * 饿汉式:
 *  在类初始化时直接创建实例对象,不管是否需要这个对象都会创建
 * 单例创建要求:
 * (1)构造器私有化
 * (2)自行创建,并且用静态变量保存
 * (3)向外提供这个实例
 * (4)强调这是一个单例,我们可以用final修饰
 */
public class Singleton1 {
    public static final Singleton1 INSTANCE = new Singleton1();
    private Singleton1(){

    }
    public static void main(String[] args) {
        Singleton1 s = Singleton1.INSTANCE;
        System.out.println(s);
    }
}
1.2、枚举式(最简洁)
/*
 * 枚举类型:表示该类型的对象是有限的几个
 * 我们可以限定为一个,就成了单例
 */
enum EnumSingleton{
    INSTANCE
}
public class Singleton2 {
    public static void main(String[] args) {
        EnumSingleton s = EnumSingleton.INSTANCE;
        System.out.println(s);
    }
}
1.3、静态代码块饿汉式(适合复杂实例化)
//静态代码块饿汉式
public class Singleton3 {
    public static final Singleton3 INSTANCE;
    public String info;
    private Singleton3(String info){
        this.info = info;
    }
    static{
        try {
            Properties pro = new Properties();

            pro.load(Singleton3.class.getClassLoader().getResourceAsStream("single.properties"));

            INSTANCE = new Singleton3(pro.getProperty("info"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public static void main(String[] args) {
        Singleton3 s = Singleton3.INSTANCE;
        System.out.println(s.info);
    }
}

二、懒汉式延迟创建对象

2.1、线程不安全(适用于单线程)
/*
 * 懒汉式:
 *  延迟创建这个实例对象,可能会出现线程不安全的情况
 *
 * (1)构造器私有化
 * (2)用一个静态变量保存这个唯一的实例
 * (3)提供一个静态方法,获取这个实例对象
 */
public class Singleton4 {
    private static Singleton4 instance;
    private Singleton4(){

    }
    public static Singleton4 getInstance(){
        if(instance == null){

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            instance = new Singleton4();
        }
        return instance;
    }
    public static void main(String[] args) throws InterruptedException, ExecutionException {

        //检查这种创建方式的线程安全性
        Callable<Singleton4> c = new Callable<Singleton4>() {

            @Override
            public Singleton4 call() throws Exception {
                return Singleton4.getInstance();
            }
        };
        //使用newFixedThreadPool线程池,设置线程数为2
        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);//false 说明这种创建单例的方式,在多线程的方式下并不安全
        System.out.println(s1);
        System.out.println(s2);

        es.shutdown();
    }
}
2.2、线程安全(适用于多线程)
/*
 * 懒汉式:
 *  延迟创建这个实例对象,针对于线程不安全的问题,可以在创建的时候,使用lock或synchronize来解决
 *
 * (1)构造器私有化
 * (2)用一个静态变量保存这个唯一的实例
 * (3)提供一个静态方法,获取这个实例对象
 */
public class Singleton5 {
    private static Singleton5 instance;
    private Singleton5(){

    }
    //并不推荐使用同步方法的方式,来完成单例模式设计,因为它锁了整个方法,其他线程想要获取实例只能等待,显然效率比较低,推荐使用DCL(Double Check Lock 双端检锁机制)来完成单例设计
    //  public synchronized static Singleton5 getInstance(){
    public static Singleton5 getInstance(){
        if(instance == null){
            //使用同步代码块来解决单例创建过程中的线程不安全问题,也可以使用同步方法来实现
            synchronized (Singleton5.class) {
                if(instance == null){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                    instance = new Singleton5();
                }
            }
        }
        return instance;
    }
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        //验证多线程环境下,这种创建线程的方式是否安全
        Callable<Singleton5> c = new Callable<Singleton5>() {

            @Override
            public Singleton5 call() throws Exception {
                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);//true
        System.out.println(s1);
        System.out.println(s2);

        es.shutdown();

    }
}
2.3、静态内部类形式(适用于多线程)
/*
 * 在内部类被加载和初始化时,才创建INSTANCE实例对象
 * 静态内部类不会自动随着外部类的加载和初始化而初始化,它是要单独去加载和初始化的。
 * 因为是在内部类加载和初始化时,创建的,因此是线程安全的
 */
public class Singleton6 {
    private Singleton6(){

    }
    private static class Inner{
        private static final Singleton6 INSTANCE = new Singleton6();
    }

    public static Singleton6 getInstance(){
        return Inner.INSTANCE;
    }
}

三、总结

  • 如果是饿汉式,枚举形式最简单
  • 如果是懒汉式,静态内部类形式最简单

原文地址:https://www.cnblogs.com/shaoyu/p/12388828.html

时间: 2024-10-08 05:01:01

实现单例设计模式的多种方式的相关文章

java单例设计模式八种方式

单例设计模式介绍 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法). 比如Hibernate的SessionFactory,它充当数据存储源的代理,并负责创建Session对象.SessionFactory并不是轻量级的,一般情况下,一个项目通常只需要一个SessionFactory就够,这是就会使用到单例模式. 单例设计模式八种方式 单例模式有八种方式: 饿汉式( ( 静态常 量) ) 饿汉式(静态

设计模式@第5章:单例设计模式

第5章:单例设计模式 一. 单例设计模式介绍 所谓类的单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例, 并且该类只提供一个取得其对象实例的方法(静态方法). 比如 Hibernate 的 SessionFactory,它充当数据存储源的代理,并负责创建 Session 对象.SessionFactory 并不是轻量级的,一般情况下,一个项目通常只需要一个 SessionFactory 就够,这是就会使用到单例模式. 二.单例设计模式八种方式 单例模式有八种方

java几种方式实现单例设计模式

单例模式的几种实现方式: 一:饿汉式单例 方式一:枚举方式获得单例对象 方式二:静态属性获得单例对象 方式三:静态方法获得单例对象 二:懒汉式单例 方式一:静态方法获得单例对象(线程安全) 方式二:内部类方式去获取单例对象 示例: 恶汉式:方式一 enum Singleton{ INSTANCE;//单例 } 恶汉式:方式二 class Singleton{ public static final Singleton INSTANCE = new Singleton();//单例 private

单例设计模式

一:单例设计模式的定义 单例设计模式,顾名思义,就是在整个程序运行过程中,只向外界提供一个对象,这样做可以避免资源的浪费,例如 我们打开回收站或者ppt时,只会启动一个窗口. 单例模式的java实现: 1:饿汉式 1 /** 2 * 3 */ 4 package com.hlcui.singleton; 5 6 /** 7 * @author Administrator 饿汉式单例类 8 */ 9 public class SingletonDemo { 10 // 1:内部创建一个对象 11

设计模式整理_单例设计模式

单例设计模式,它确保一个类只有一个实例,并提供一个全局访问点. 由于单例设计模式对应的类只能创建一个对象,因此它所对应的方法必须是static(不是static只有创建对象才能调用). 以下是单例模式的一个经典实现:采用了延迟加载对象的例子. public class Single1 { private static Single1 single; //利用一个静态变量来记录Single1的唯一实例,这里没有直接声明,采用了延迟加载模式. private Single1(){} //把构造器声明

【学习笔记】单例设计模式笔记

单例设计模式是常见的设计模式之一.通过单例实现所需求类在系统中只存在唯一一个实例. 单例设计模式分两种:懒汉单例设计模式和饿汉单例设计模式,两者设计思路一致,实现有微小不同. 实现代码: 1 public class HungryMan { 2 3 private HungryMan(){};//私有的构造方法保证HungryMan类无法在外部使用构造方法实例化 4 private static final HungryMan hungryMan=new HungryMan();//在类内定义一

Java——单例设计模式

设计模式:解决某一类问题最行之有效的方法.Java中23种设计模式:单例设计模式:解决一个类在内存中只存在一个对象. 想要保证对象唯一.1,为了避免其他程序过多建立该类对象.先禁止其他程序建立该类对象2,还为了让其他程序可以访问到该类对象,只好在本类中,自定义一个对象.3,为了方便其他程序对自定义对象的访问,可以对外提供一些访问方式 这三部怎么用代码体现呢?1,将构造函数私有化.2,在类中创建一个本类对象.3,提供一个方法可以获取到该类对象. 对于事物该怎么描述,还怎么描述.当需要将该事物的对象

线程安全的懒汉式单例设计模式

首先回顾一下单利设计模式: 单利设计模式是通过某种方式使某个类只能创建一个对象实例供外界使用. 单利设计模式分为懒汉式和饿汉式: 饿汉式是线程安全的: 1 //饿汉式单利设计模式: 2 class Single{ 3 private static final Single single = new Single(); 4 private Single(){} 5 public static Single getInstance(){ 6 return s; 7 } 8 } 饿汉式实现线程安全,可

设计模式总纲——单例设计模式

前两天写了设计模式总纲,今天就来讲讲我们在工程代码中最最最常用的设计模式了——单例设计模式,这个模式在工程代码上的出现率几乎为99.99999%,但是虽然很常用,但是用的好的人却不多,今天我们就来深入的说一说单例设计模式. 在学习一项新的知识之前,我们都要向自己提出三个问题,为什么要用这个知识,这个知识用在哪里,这个知识怎么用?既 why,where,how,3W模式,我们先来谈谈为什么需要单例设计模式,先来想想,如果一个工具类,比如一个读取配置文件的工具类,这类工具只是特定的功能类,既读取指定