单例模式

  单例模式,顾名思义,在程序运行中,实例化某个类时只实例化一次,即只有一个实例对象存在。例如在古代,一个国家只能有一个皇帝,在现代则是主席或总统等。

  在Java语言中单例模式有以下实现方式

1.饿汉式

import org.junit.jupiter.api.Test;

public class Singleton {
//静态成员变量
private static Singleton singleton = new Singleton();
private String name; public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
//构造函数私有化
private Singleton(){
}
//返回静态资源中Singleton实例
public static Singleton getInstance() {
return singleton;
}
/**
* 单元测试
*/
@Test
public void testSingleton() {
//通过调用类的静态方法返回类的实例对象
Singleton s1 = Singleton.getInstance();
Singleton s2 = Singleton.getInstance();
s1.setName("zhangsan");
s2.setName("lisi");
System.out.println(s1.getName());
System.out.println(s2.getName());
}
}

  在类加载时,直接将实例对象初始化,并且该实例是静态的,属于类的成员变量,通过调用类的静态方法返回该对象。  

  运行testSingleton单元测试,输出的两行都是lisi,因为s1,s2指向的同一个实例对象,这个对象在类创建的时候就存在了。

  饿汉式是线程安全的,不管系统的那一个线程获取这个对象,他们都是该类同一个对象。缺点是在程序在一开始就创建了该对象,占用内存空间。下面这种实现方式增加判断,在程序调用时才实例化该对象。

2.懒汉式

import org.junit.jupiter.api.Test;

public class Singleton {
//不初始化实例对象
private static Singleton singleton = null;
private String name; public String getName() {
return name;
}
//构造函数私有化
private Singleton(){
}
public void setName(String name) {
this.name = name;
}
//当被调用时才动态实例化
public static Singleton getInstance() {
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}

  懒汉式解决了饿汉式的实例对象初始化占用内存的情况,但是懒汉式存在线程安全的问题,当多个线程同时访问getInstance()方法时,有可能在第一个线程进入if语句是还没new Singleton()时,这时第二个线程判断if的时候就会为真,则会创建新的实例,单例模式设计失败。

  这时需要在getInstance()方法上添加synchronized修饰符,表示线程同步,即当一个线程访问该方法时,其他线程需要等待其释放资源。

public static synchronized Singleton getInstance() {
if(singleton == null) {
singleton = new Singleton();
}
return singleton;
}

  这样解决了懒汉式的线程不安全的问题,但是这样会降低系统的性能,当一个线程占用了该资源,其他的线程只能等待,系统的性能大大下降。于是乎第三种实现模式,对懒汉式进行了改进。

3.双重检测

public static  Singleton getInstance() {
if(singleton == null) {
synchronized (Singleton.class) {
if(singleton==null) {
singleton = new Singleton();
}
}
}
return singleton;
}

  双重检测,线程访问时有两次检测。

  这里将synchronized放到判断语句里面,这样当第一个线程调用getInstance()方法时,singleton为空,进入synchronized代码块,其他的线程即使也判断singleton为空,则需要等待第一个线程完成资源的使用,这样保证了线程的安全。

  当实例化对象完成时,其他的线程调用getInstance()方法时,直接返回Singleton对象即可,不用再等待,这一点优化了系统,提高了系统的性能。

4.总结

  模式来源于生活。本文用Java语言实现了单例模式。三种实现方式都是线程安全的,饿汉式比较占用内存空间;懒汉式则降低了系统的性能;双重检测是懒汉式的升级,即能保证线程的安全,也能以懒加载的方式实现单例模式,在大规模系统中节省对象的创建时间,提高系统的性能。在系统中共享同一个资源或同一个对象,则可利用单例模式来实现。

  参考B站视频https://www.bilibili.com/video/av34162848

单例模式--java代码实现的更多相关文章

  1. 让JAVA代码跑得更快

    本文简单介绍一下在写代码过程中用到的一些让JAVA代码更高效的技巧. 1.   将一些系统资源放在池中(如数据库连接, 线程等) 在standalone的应用中, 数据库连接池可以使用一些开源的连接池 ...

  2. ActiveMQ——activemq的使用java代码实例(精选)

    ActiveMQ 在java中的使用,通过单例模式.工厂实现 Jms规范里的两种message传输方式Topic和Queue,两者的对比如下表():   Topic Queue 概要 Publish  ...

  3. 对一致性Hash算法,Java代码实现的深入研究

    一致性Hash算法 关于一致性Hash算法,在我之前的博文中已经有多次提到了,MemCache超详细解读一文中"一致性Hash算法"部分,对于为什么要使用一致性Hash算法.一致性 ...

  4. 怎样编写高质量的java代码

    代码质量概述     怎样辨别一个项目代码写得好还是坏?优秀的代码和腐化的代码区别在哪里?怎么让自己写的代码既漂亮又有生命力?接下来将对代码质量的问题进行一些粗略的介绍.也请有过代码质量相关经验的朋友 ...

  5. 数据结构笔记--二叉查找树概述以及java代码实现

    一些概念: 二叉查找树的重要性质:对于树中的每一个节点X,它的左子树任一节点的值均小于X,右子树上任意节点的值均大于X. 二叉查找树是java的TreeSet和TreeMap类实现的基础. 由于树的递 ...

  6. java代码的初始化过程研究

        刚刚在ITeye上看到一篇关于java代码初始化的文章,看到代码我试着推理了下结果,虽然是大学时代学的知识了,没想到还能做对.(看来自己大学时掌握的基础还算不错,(*^__^*) 嘻嘻……)但 ...

  7. JDBC——Java代码与数据库链接的桥梁

    常用数据库的驱动程序及JDBC URL: Oracle数据库: 驱动程序包名:ojdbc14.jar 驱动类的名字:oracle.jdbc.driver.OracleDriver JDBC URL:j ...

  8. 利用Java代码在某些时刻创建Spring上下文

    上一篇中,描述了如何使用Spring隐式的创建bean,但当我们需要引进第三方类库添加到我们的逻辑上时,@Conponent与@Autowired是无法添加到类上的,这时,自动装配便不适用了,我们需要 ...

  9. lombok 简化java代码注解

    lombok 简化java代码注解 安装lombok插件 以intellij ide为例 File-->Setting-->Plugins-->搜索"lombok plug ...

随机推荐

  1. ssh运行环境搭建及测试

    一.运行环境 1.Spring环境 Spring是一站式开发框架,在SSH中主要有以下作用,就像一个大管家: 控制反转(Inversion of Control):类不再自己进行类创建,而是交给Spr ...

  2. Hystrix 熔断机制原理

    相关配置 circuitBreaker.enabled 是否开启熔断 circuitBreaker.requestVolumeThreshold 熔断最低触发请求数阈值 circuitBreaker. ...

  3. C++中遍历读取数组中的元素

    答案来源:https://zhidao.baidu.com/question/187071815.html 对于字符数组str[N],判断方法有以下三种: 第一种:用库函数strlen 1 len = ...

  4. remove duplicate of the sorted array

    description: Given a sorted array, remove the duplicates in place such that each element appear only ...

  5. Jquery浅克隆与深克隆

    Jquery浅克隆与深克隆 JavaScript部分 $("div").on('click', function() {//执行操作}) //clone处理一 $("di ...

  6. CRM客户关系管理系统(九)

    第九章.filter_horizontal优化和kingadmin删除功能 9.1.filter_horizontal优化 (1)添加Choose ALL 和Remove ALL table_obj_ ...

  7. 高通spi 屏幕 -lk代码分析

    lk SPI驱动 1. 初始化时钟 在lk中,我们是从kmain开始执行下来的,而执行顺序则是先初始化时钟,也就是在platform_early_init函数中开始执行的: 在这里我们需要修改这个函数 ...

  8. mysql 基础语法掌握~ This is just the beginning.

    create database 数据库名; drop database 数据库名; use 数据库名; create table table_name ( column_name, column_ty ...

  9. 在C++98基础上学习C++11新特性

    自己一直用的是C++98规范来编程,对于C++11只闻其名却没用过其特性.近期因为工作的需要,需要掌握C++11的一些特性,所以查阅了一些C++11资料.因为自己有C++98的基础,所以从C++98过 ...

  10. Webpack 热部署检测不到文件的变化

    最近在用webpack开发,突然发现热部署检测不到文件的变化,相关webpack的代码并没有发生改变,而且同事们的webpack都是正常的,不能热部署严重影响我的开发效率. 网上查了一下原来 Webp ...