单例模式-java实现

news2024/12/22 23:44:56

介绍

单例模式的意图:保证某个类在系统中有且仅有一个实例。

我们可以看到下面的类图:一般的单例的实现,是属性中保持着一个自己的私有静态实例引用,还有一个私有的构造方法,然后再开放一个静态的获取实例的方法给外界获取实例对象。

 

 

代码实现

在java中有两种实现的方法

  • 饿汉式:在类加载的时候就创建好实例
  • 懒汉式:在请求实例时才创建实例

饿汉式

在类加载的时候就创建好实例

public class TestObj {
    private static TestObj testObj=new TestObj();
    //构造方法私有化
    private TestObj(){

    }
    //提供一个外界获取单实例的静态方法
    public static  TestObj getTestObj(){
        return testObj;
    }
}

懒汉式

由于java是多线程的,很有可能多个线程同时进入,导致创建多个实例,于是我们要使用锁机制来让线程之间互斥访问

public class TestObj2 {
    //初始,维护一个静态的空引用
    private static TestObj2 testObj2=null;
    //私有的构造方法
    private TestObj2(){

    }
    //提供给外界获取单实例的静态方法
    public static TestObj2 getTestObj2(){
        //在这里,由于java是多线程的,很有可能多个线程同时进入,导致创建多个实例,于是我们要使用锁机制来让线程之间互斥访问
        //多线程同时判断,如果不为null,直接返回
        if (testObj2!=null){
            return testObj2;
        }
        //使用同步代码块进行线程互斥访问
        synchronized (Object.class){
            //其他线程进入以后,如果已经创建好了对象,则直接返回
            if (testObj2!=null){
                return testObj2;
            }
            else {
                //初始化单实例
                testObj2=new TestObj2();
            }

        }
        return testObj2;

    }
}

我们这里测试一下:

创建三个线程同时去获取实例,看输出的地址是否一样

//创建一个runable接口
class DoTask implements Runnable{
    @Override
    public void run() {
        //获取实例对象并输出
        TestObj2 testObj2 = TestObj2.getTestObj2();
        System.out.println(testObj2);
    }
}

class Main{
    public static void main(String[] args) {
        Runnable runnable=new DoTask();
        //创建多个线程去获取实例
        Thread thread1=new Thread(runnable);
        Thread thread2=new Thread(runnable);
        Thread thread3=new Thread(runnable);
        thread1.start();
        thread2.start();
        thread3.start();
    }
}

运行结果:

可以看到输出的三个地址都是相同的,因此我们上面的懒汉式代码是完全可行的,这里仅仅讨论单服务器的情况,如果是分布式系统中的单实例,就要考虑使用分布式锁,或者redis,zookeeper等分布式协调工具去完成了

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/849272.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

golang内存对齐

为什么要内存对齐? CPU访问内存时,以CPU的位数为单位进行访问。 如果访问未对齐的内存,处理器需要做两次内存访问,对齐的内存的访问可能仅需要一次,利用内存对齐后提升读取速度。 golang结构体内存对齐规则 在代码编译…

MySql学习3:常用函数

常用字符串函数 CHAR_LENGTH(s):返回字符串的长度 select *, char_length(name) as nameLength from emp;CONCAT(s1,s2…sn):字符串拼接 select name,concat(name,入职时间:,entrydata) as 入职时间 from emp;CONCAT_WS(x, s1,s2…sn)&a…

24v转3.3v输出3A用什么芯片

问:客户需要一个能够将24V输入电压转换为3.3V输出电压,并且能够提供1-3A的电流输出的芯片。还希望它能够内置MOS管。有什么推荐的型号吗?(vin24v、5v,vout3.3v,Io1-3A) 答:推荐使用…

Unity游戏源码分享-塔防游戏保卫兔子的食物CarrotFantasy

Unity游戏源码分享-塔防游戏保卫兔子的食物CarrotFantasy 经典塔防游戏,可发布PC、Andoid、IOS、Web等 下载地址:https://download.csdn.net/download/Highning0007/88189987

【Spring Boot】Thymeleaf模板引擎 — Thymeleaf页面布局

Thymeleaf页面布局 熟悉Thymeleaf的语法和表达式后,后面开发起来会更加得心应手。接下来好好研究一下Thymeleaf如何实现完整的Web系统页面布局。 1.引入代码片段 在模板中经常希望包含来自其他模板页面的内容,如页脚、页眉、菜单等。为了做到这一点&a…

【从零开始学习JAVA | 三十九篇】深入多线程

目录 前言: ​1.线程的寿命周期​ 2.线程的安全问题 3.锁 同步代码块: 同步方法: 死锁: 4.生产者和消费者模式(等待唤醒机制) 总结: 前言: 当今软件开发领…

构建Docker容器监控系统(2)(Cadvisor +Prometheus+Grafana)

Cadvisor产品简介 Cadvisor是Google开源的一款用于展示和分析容器运行状态的可视化工具。通过在主机上运行Cadvisor用户可以轻松的获取到当前主机上容器的运行统计信息,并以图表的形式向用户展示。 接着上一篇来继续 部署Cadvisor 被监控主机上部署Cadvisor容器…

Echart(v5)实现中国地图区域图

一、需求背景 需要实现一个中国地图的区域图(区域级别到市),并且指定区域可以高亮。 二、相关工具 1、中国的GeoJSON数据获取:DataV.GeoAtlas地理小工具系列 2、Echart组件库 Apache ECharts 三、实现 echart配置: …

MySQL查看当前数据库视图-SQL语句

引言 查询语句为: show full tables where table_type 可查询当前数据库表 一,创建一个视图 # 创建视图 create view v_stu as # 视图内容(连接的一个表) select name from t_stu union all select tname from t_teach; 二&…

RISC-V云测平台:Compiling The Fedora Linux Kernel Natively on RISC-V

注释:编译Fedora,HS-2 64核RISC-V服务器比Ryzen5700x快两倍! --- 以下是blog 正文 --- # Compiling The Fedora Linux Kernel Natively on RISC-V ## Fedora RISC-V Support There is ongoing work to Fedora to support RISC-V hardwar…

2.4 网络安全新技术

数据参考:CISP官方 目录 云计算安全大数据安全移动互联网安全物联网安全工业互联网安全 一、云计算安全 1、云计算定义 云计算是指通过网络访问可扩展的、灵活的物理或虚拟共享资源池,并按需自助获取和管理资源的模式。在云计算中,计算资…

Goland搭建远程Linux开发

Windows和Linux都需要先构建好go环境,启用ssh服务。 打开Windows上的Goland,建立项目。 点击添加配置,选择go构建 点击运行于,选择ssh 填上Linux机器的IP地址和用户名 输入密码 没有问题 为了不让每次运行程序和调试程序都生…

AIGC自动生成内容真的好吗

一、前言 博主认为某些技术领域的发展对人类而言,并没有多大的益处。反而让人类更加困扰。纵观这几十年的技术发展,日新月异,但是人类生活的幸福指数并没有提高,反而产生了无数的社会问题。 AI大模型迅速发展,A…

【Spring专题】手写简易Spring容器过程分析

前置知识 《【Spring专题】Spring底层核心原理解析》 思路整理 我们在上一节《【Spring专题】Spring底层核心原理解析》课里面有简单分析过一个Spring容器的一般流程,所以,本节课我们这里尝试写一下简易的Spring容器。 手写源码示例 一、手写前的准…

FirmAE 模拟固件

一、介绍 FirmAE目标是创造一个可以供用户动态调试分析的环境,而不是复现和硬件一模一样的环境,,其卖点是大规模(Large-Scale)。 论文开头就直指“友商”Firmadyne,提出其模拟成功率低等问题, 其将原本Firmadyne的成功率16.28%提高…

Navicat 导出excel表数据结构

效果展示: 实现过程: 1 打开Navicat 执行以下SQL,注意:将以下SQL中的数据库名称和表名称替换。 SELECT COLUMN_NAME 列名, COLUMN_TYPE 数据类型, DATA_TYPE 字段类型, CHARACTER_MAXIMUM_LENGTH 长度, IS_NULLABLE 是否为空, C…

代码随想录算法学习心得 50 | 739.每日温度、496.下一个更大元素I...

一、每日温度 链接:力扣 描述如下:给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高&…

pytest自动化测试框架之标记用例(指定执行、跳过用例、预期失败)

pytest中提供的mark模块,可以实现很多功能,如: 标记用例,即打标签skip、skipif标记跳过,skip跳过当前用例,skipif符合情况则跳过当前用例xfail标记为预期失败 标记用例 有时候我们可能并不需要执行项目中…

HTTP协议——应用层

HTTP协议 只要保证, 一端发送时构造的数据, 在另一端能够正确的进行解析, 就是ok的. 这种约定, 就是 应用层协议 HTTP简介 HTTP(Hyper Text Transfer Protocol)协议又叫做超文本传输协议,是一个简单的请求-响应协议,HTTP通常运行…

Spring-1-深入理解Spring XML中的依赖注入(DI):简化Java应用程序开发

学习目标 前两篇文章我们介绍了什么是Spring,以及Spring的一些核心概念,并且快速快发一个Spring项目,以及详细讲解IOC,今天详细介绍一些DI(依赖注入) 能够配置setter方式注入属性值 能够配置构造方式注入属性值 能够理解什么是自动装配 一、…