当前位置: 首页 > article >正文

单例模式的介绍

单例模式

文章目录

  • 单例模式
    • 介绍
    • 常见形式
      • 饿汉式
      • 懒汉式

介绍

介绍:单例设计模式,即某个类在整个系统中只能有一个实例对象可被获取和使用的代码块模式。

例如: 代表JVM运行环境的Runtime类

特点:

1.是某个类只能有一个实例;

  • 构造器私有化

2.是它必须自行创建这个实例;

  • 含有一个该类的静态变量来保存这个唯一的实例

3.是它必须自行向整个系统提供这个实例;

  • 对外提供获取该实例对象的方式:
  • 直接暴露
  • 用静态变量的get方法获取

常见形式

饿汉式

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

  • 直接实例化饿汉式(简洁直观)
  • 枚举式(最简洁)
  • 静态代码块饿汉式(适合复杂实例化)

懒汉式

懒汉式:延迟创建对象

  • 线程不安全(适用于单线程)
  • 线程安全(适用于多线程)
  • 静态内部类形式(适用于多线程)

饿汉式直接实例化

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

    }
}
//测试代码块
package com.interview.singleton.test;

import com.interview.singleton.Singleton1;

public class Singletontest1 {
    public static void main(String[] args) {
        Singleton1 singleton1 =Singleton1.INSTANCE;
        System.out.println(singleton1);
    }
}

饿汉式枚举式

package com.interview.singleton;

/**
 * 饿汉式单例模式
 * 枚举类型  表示该类型的对象是有限几个
 * 我们可以限定为一个  就成了单例
 */
public enum  Singleton2 {
    INSTANCE
}
//测试代码块
package com.interview.singleton.test;

import com.interview.singleton.Singleton2;

public class Singletontest2 {
    public static void main(String[] args) {
        Singleton2 singleton2 = Singleton2.INSTANCE;
        System.out.println(singleton2);
    }
}

静态代码块饿汉式

package com.interview.singleton;

import java.io.IOException;
import java.util.Properties;

public class Singleton3 {
    public static Singleton3 INSTANCE;
    private String info;
    //静态代码块
    static {
        Properties pro = new Properties();
        try {
            //加载配置文件
            pro.load(Singleton3.class.getClassLoader().getResourceAsStream("com/interview/singleton/single.properties"));
        } catch (IOException e) {
            throw new RuntimeException();
        }
        INSTANCE = new Singleton3(pro.getProperty("info"));
    }
    //构造器私有化
    private Singleton3(String s) {
        this.info = s;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

    @Override
    public String toString() {
        return "Singleton3{" +
                "info='" + info + '\'' +
                '}';
    }
}
//测试代码块
package com.interview.singleton.test;

import com.interview.singleton.Singleton3;

public class SingletonTest3 {
    public static void main(String[] args) {
        Singleton3 s = Singleton3.INSTANCE;
        System.out.println(s);
    }
}

懒汉式线程不安全

package com.interview.singleton;

public class Singleton4 {
    /**
     * 懒汉式单例模式 延迟创建实例对象
     * 1.构造器私有化
     * 2.用静态变量保存这个唯一的实例
     *
     * 单线程模式下  不会出现线程安全问题
     */
    private static Singleton4 instance;
    private Singleton4(){

    }
    public static Singleton4 getInstance(){
        if(instance==null){
            try {
                //休眠100ms
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            instance = new Singleton4();
        }
        return instance;
    }
}
//测试代码块
package com.interview.singleton.test;

import com.interview.singleton.Singleton4;

import java.util.Calendar;
import java.util.concurrent.*;

public class SingletonTest4 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
       /* 单线程模式  不会出现线程安全问题
        Singleton4 s1 = Singleton4.getInstance();
        Singleton4 s2 = Singleton4.getInstance();
        System.out.println(s1==s2);
        System.out.println(s1);
        System.out.println(s2);*/
        //多线程
        Callable<Singleton4> c = new Callable<Singleton4>() {
            @Override
            public Singleton4 call() throws Exception {
                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();
    }
}

懒汉式线程安全

package com.interview.singleton;

public class Singleton5 {
    /**
     * 懒汉式单例模式 延迟创建实例对象
     * 1.构造器私有化
     * 2.用静态变量保存这个唯一的实例
     * 解决了多线程下的安全问题
     */
    private static Singleton5 instance;
    private Singleton5(){

    }
    public static Singleton5 getInstance(){
        //当instance 为空时才进入  提高了效率
        if(instance==null){
            //加锁可以解决多线程同时访问而造成的线程不安去问题 加锁是为了只让一个线程进来
            synchronized (Singleton5.class){
                //当线程进来以后再判断是否为空
                if(instance==null){
                    try {
                        //休眠100ms
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    instance = new Singleton5();
                }
            }
        }
        //如果instance!=null 则直接返回  提高了效率
        return instance;
    }
}
//测试代码块
package com.interview.singleton.test;

import com.interview.singleton.Singleton4;
import com.interview.singleton.Singleton5;

import java.util.concurrent.*;

public class SingletonTest5 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
       /* 单线程模式  不会出现线程安全问题
        Singleton4 s1 = Singleton4.getInstance();
        Singleton4 s2 = Singleton4.getInstance();
        System.out.println(s1==s2);
        System.out.println(s1);
        System.out.println(s2);*/
        //多线程
        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);
        System.out.println(s1);
        System.out.println(s2);

        es.shutdown();
    }
}

懒汉式静态内部类形式

package com.interview.singleton;

/**
 * 在内部类被加载和初始化时,才会创建INSTANCE实例对象
 * 静态内部类不会自动随着外部类的加载和初始化而初始化,它是要单独去加载和初始化的
 * 因为是在内部类加载和初始化时创建的  因此是线程安全的
 */
public class Singleton6 {

    private Singleton6() {

    }
    private static class Inner{
        private static final Singleton6 INSTANCE = new Singleton6();
    }
    public static Singleton6 getInstance(){
        return Inner.INSTANCE;
    }
}
//测试代码块
package com.interview.singleton.test;

import com.interview.singleton.Singleton6;

import java.util.concurrent.*;

public class SingletonTest6 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
       /* 单线程模式  不会出现线程安全问题
        Singleton4 s1 = Singleton4.getInstance();
        Singleton4 s2 = Singleton4.getInstance();
        System.out.println(s1==s2);
        System.out.println(s1);
        System.out.println(s2);*/
        //多线程
        Callable<Singleton6> c = new Callable<Singleton6>() {
            @Override
            public Singleton6 call() throws Exception {
                return Singleton6.getInstance();
            }
        };
        ExecutorService es = Executors.newFixedThreadPool(2);
        Future<Singleton6> f1 = es.submit(c);
        Future<Singleton6> f2 = es.submit(c);
        Singleton6 s1 = f1.get();
        Singleton6 s2 = f2.get();
        System.out.println(s1==s2);
        System.out.println(s1);
        System.out.println(s2);

        es.shutdown();
    }
}

用到的配置文件信息

创建一个sing.properties的文件

内容:info = “hello world”

小结

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

http://www.kler.cn/news/17881.html

相关文章:

  • Yolov1 源码讲解 loss.py
  • 【C++】 类练习---封装链表、人物移动
  • gitlab使用docker简单快速部署
  • 数字座舱带动液晶仪表升级,哪些企业「领跑」前装量产份额
  • 20. 资源的调度——Node 亲和性(Node Affinity)
  • 亚马逊选品有什么技巧?品选对了可以带来什么好处?
  • 【图像分割】视觉大模型SEEM(Segment Everything Everywhere All at Once)原理解读
  • 登顶Nature 正刊!百度生物计算用AI首次实现mRNA领域重大进展
  • OpenFeign服务接口调用
  • 【Admin后台管理】Geodjango后台显示地图并加载空间字段
  • 计算机智能系统有哪些SCI期刊? - 易智编译EaseEditing
  • React实战模版
  • 【P6】JMeter HTTP Cookie管理器
  • 【算法导论】算法分析与设计_理论知识点(可用于备考)
  • 玩机搞机--定制系统 编译系统选项 隐藏设置 关闭app联网 增加设置选项
  • 现在的00后,真是卷死了呀,想离职了·····
  • SpringBoot的创建和使用
  • ios app真机测试到上架App Store详细教程-必看
  • Leetcode刷题之复制带随机指针的链表
  • 无线之红外线技术的组网方式详解
  • 【lambda表达式传值问题研究】
  • node.js+vue鲜花销售网站
  • 拥抱生成式大模型 -- langchain篇 (博客搬家至知乎,同步更新)
  • Reference Type 解析 this 丢失问题
  • 极简Python--列表
  • windows下部署GTK环境
  • 一个让人类窒息的AI工具,或许未来人工智能真的能代替人类!
  • 软件架构师的修炼之道
  • CE游戏特例说明
  • 提升V-Ray渲染效率的五个实用技巧!