单例模式

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

  在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. Ubuntu硬盘空间清理

    1.删除多余的安装下载文件: sudo aptitude autoclean sudo aptitude clean 2.删除多余的内核版本: sudo apt-get autoremove 4.去/ ...

  2. Spring结合log4j(slf4j)

    maven依赖         <!-- slf4j (级联:log4j/slf4j-api) --> <dependency>         <groupId> ...

  3. 图片与base64的互转

    /// <summary>        /// 把图片转换到文本信息        /// </summary>        /// <param name=&quo ...

  4. Django rest framework源码分析(3)----节流

    目录 Django rest framework(1)----认证 Django rest framework(2)----权限 Django rest framework(3)----节流 Djan ...

  5. The more,the better。

    贪婪是好的, 贪婪是对的, 贪婪是有用的, 贪婪是可以清理一切的, 贪婪是不断进化和进步的精华所在, 贪婪就是一切形式所在: 对于生活,对于爱情,对于知识我们一定要贪婪, 贪婪就是人们的动力. The ...

  6. mysql索引sql优化方法、步骤和经验

    MySQL索引原理及慢查询优化 http://blog.jobbole.com/86594/ 细说mysql索引 https://www.cnblogs.com/chenshishuo/p/50300 ...

  7. Java NIO SocketChannel套接字通道

    原文链接:http://tutorials.jenkov.com/java-nio/socketchannel.html 在Java NIO体系中,SocketChannel是用于TCP网络连接的套接 ...

  8. 第五章——支持向量机(Support Vector Machines)

    svm可用于线性或非线性分类.回归.甚至异常检测. svm尤其适用于中小数据集的复杂分类问题. 5.1 Linear SVM Classification svm对feature scales敏感,如 ...

  9. vm12 和14密钥

    vm12:5A02H-AU243-TZJ49-GTC7K-3C61N vm14:FF31K-AHZD1-H8ETZ-8WWEZ-WUUVA

  10. C#中的is和as

    is检查一个对象是否兼容于指定的类型,不返回Boolean值.注意is操作符永远不会抛异常.is操作符通常这样使用: if(o is Employee) { Employee e=(Employee) ...