PS:首先我们要先知道什么是单例,为什么要用单例,用的好处是什么等问题来看。

1:java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍两种:懒汉式单例、饿汉式单例

单例模式有以下特点:  

  1、单例类只能有一个实例。
  2、单例类必须自己创建自己的唯一实例。
  3、单例类必须给所有其他对象提供这一实例。

目的

  单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。

2:懒汉式

先把单例类写出来

public class SingletonTest {
//懒汉式单例类.在第一次调用的时候实例化自己
private SingletonTest() {}
private static SingletonTest single=null;
//静态工厂方法
public static SingletonTest getInstance() {
if (single == null) {
single = new SingletonTest();
System.out.println("创建一次");
}
return single;
} public void show(){
System.out.println("我是show");
} }

这里直接上代码,代码中有详解

public class SingletonTest2 {

    public static void main(String[] args) {
// TODO Auto-generated method stub
//故意写获取两次,创建两个对象
SingletonTest singleton=SingletonTest.getInstance();
SingletonTest singleton2=SingletonTest.getInstance(); //Singleton对象只创建一次,但是写两次还是可以的,而且方法都是可以调用的,但是看下面
singleton.show();
singleton2.show(); //两个对象的表现形式一样
if(singleton == singleton2){
System.out.println("该对象的字符串表示形式:");
System.out.println("singleton :"+singleton.toString());
System.out.println("singleton2:"+singleton2.toString());
}
}

由上面的图可以看出就算多创建几个对象,在底部也是只有一个singleton对象实例,而且创建出来的对象的字符串表现形式也是一样的,有的人肯定有疑问,那平常两个对象是什么样子的呢,我下面给你解释说明,在这之前我写说一下这个懒汉式需要注意的地方,它是线程不安全的,并发环境下很可能出现多个Singleton实例,有很多方法可以解决,比如说同步锁,静态内部类等,这里主要说静态内部类,这个比较好点,

public class Singleton3 {
private static class SingletonHolder {
private static final Singleton3 INSTANCE = new Singleton3();
}
private Singleton3 (){}
public static final Singleton3 getInstance() {
System.out.println("singleton创建");
return SingletonHolder.INSTANCE;
}
}

调用:

Singleton3 singleton3=Singleton3.getInstance();
Singleton3 singleton4=Singleton3.getInstance();
if(singleton3 == singleton4){
System.out.println("该对象的字符串表示形式:");
System.out.println("singleton3:"+singleton3.toString());
System.out.println("singleton4:"+singleton4.toString());
}

结果图:

这里我也是创建了两个对象来说明,神奇的是打印了两次singleton创建,这难道是又创建成功了的对象吗?答案是:虽然打印了两次,对象名也有两个,但是该对象的字符串表示形式还是一样的,而且大家都知道static的用法,就是在类被加载的同时该singleton对象就已经被创建,后期不会再被创建,就算后期自己又调用了getInstance()方法,但底层还是公用的一个Singleton对象.

同样,我写了一个普通的类,来同时创建两个对象,并且打印他们的toString()方法,如下:

     QuBie qb1=new QuBie();
QuBie qb2=new QuBie();
if(qb1 == qb2){
System.out.println("该对象的字符串表示形式:");
System.out.println("singleton3:"+qb1.toString());
System.out.println("singleton4:"+qb2.toString());
}else{
System.out.println("该对象的字符串表示形式:");
System.out.println("singleton3:"+qb1.toString());
System.out.println("singleton4:"+qb2.toString());
}

由此可看出来对象的字符串表示形式是不一样的

3:饿汉式单例

饿汉式单例类.在类初始化时,已经自行实例化

public class Singleton1 {
private Singleton1() {}
private static final Singleton1 single = new Singleton1();
//静态工厂方法
public static Singleton1 getInstance() {
return single;
}
}

因为这本身就是static修饰的方法,所以是在类加载的时候被创建,后期不会再改变,所以线程是安全的。

4:双检锁/双重校验锁

描述:采用双锁机制,安全且在多线程情况下能保持高性能。多线程安全

 

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

这里的两次判断,第一判断:效率,第二判断:避免同步。之所以这样是因为避免加锁后,再次加锁。大大增强了执行效率。

(适配器、单例、静态代理、简单工厂设计模式)https://www.cnblogs.com/cmusketeer/p/8146510.html

Java-单例模式详解(图文并茂,简单易懂)的更多相关文章

  1. 9种Java单例模式详解(推荐)

    单例模式的特点 一个类只允许产生一个实例化对象. 单例类构造方法私有化,不允许外部创建对象. 单例类向外提供静态方法,调用方法返回内部创建的实例化对象.  懒汉式(线程不安全) 其主要表现在单例类在外 ...

  2. Java 单例模式详解

    概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. ...

  3. 【JAVA单例模式详解】

    设计模式是一种思想,适合于任何一门面向对象的语言.共有23种设计模式. 单例设计模式所解决的问题就是:保证类的对象在内存中唯一. 举例: A.B类都想要操作配置文件信息Config.java,所以在方 ...

  4. Java 单例模式详解(转)

    概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. ...

  5. 9种Java单例模式详解

    单例模式的特点 一个类只允许产生一个实例化对象. 单例类构造方法私有化,不允许外部创建对象. 单例类向外提供静态方法,调用方法返回内部创建的实例化对象. 懒汉式(线程不安全) 其主要表现在单例类在外部 ...

  6. java单例模式详解

    饿汉法 饿汉法就是在第一次引用该类的时候就创建对象实例,而不管实际是否需要创建.代码如下: public class Singleton { private static Singleton = ne ...

  7. Java集合详解6:TreeMap和红黑树

    Java集合详解6:TreeMap和红黑树 初识TreeMap 之前的文章讲解了两种Map,分别是HashMap与LinkedHashMap,它们保证了以O(1)的时间复杂度进行增.删.改.查,从存储 ...

  8. Java虚拟机详解----JVM常见问题总结

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  9. Java面向对象详解

    Java面向对象详解 前言:接触项目开发也有很长一段时间了,最近开始萌发出想回过头来写写以前学 过的基础知识的想法.一是原来刚开始学习接触编程,一个人跌跌撞撞摸索着往前走,初学的时候很多东西理解的也懵 ...

  10. Java synchronized 详解

    Java synchronized 详解 Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 1.当两个并发线程访问同一个对象object ...

随机推荐

  1. [flask实践] 解决qq邮箱/mysql的相关配置问题

    笔者经过flask web(Miguel著,封面是一条狗)一书的学习,打算实现一个旅游类网站,在此过程中发现,相对于书中的flasky博客程序,需要作出一些改变: 1. 注册邮箱:国内要使用126,q ...

  2. dedecms注入漏洞

    版本:Powered by DedeCMSV57_GBK © 2004-2011 DesDev Inc. 漏洞利用EXP:plus/recommend.php?action=&aid=1&am ...

  3. mysql安装后服务启动不了(总结)

    mysql安装后服务启动不了 1.1 前言 最近真的是倒霉到家,装个mysql都能把所有的问题给问候了一遍······不过这也是一个宝贵的经验,得好好总结下,毕竟也不知道以后会不会再次遇到.如果有网友 ...

  4. windows 下更新 npm 和 node

    原文链接 公司的新项目要启动了,需要使用 Angular 4.0,并且使用 webpack 工具进行打包.所以就需要安装 node.node 的安装很简单,在 node 的官网 nodejs.org  ...

  5. 利用nginx实现负载均衡和动静分离

    1.Nginx介绍 Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器 . Nginx 是由 ...

  6. FastDFS教程Ⅲ-文件服务器扩容

    1.简介     FastDFS文件服务器在设计时,为了支持大容量,存储节点(服务器)采用了分卷(或分组)的组织方式.存储系统由一个或多个卷组成,卷与卷之间的文件是相互独立的,所有卷的文件容量累加就是 ...

  7. Python3学习笔记2:简易Web爬虫

    开发环境 基础语法那章的内容我是在Docker容器中玩的,但是真正做项目的时候,没有IDE的强大辅助功能来协助的话是很累人的一件事.因此从本文中,我选择使用Jetbrain的Pycharm这个IDE来 ...

  8. dubbo源码—SPI

    Java中的SPI SPI,Service Provider Interface,java中提供的一种使程序可扩展的方式,系统定义好接口规范,供其他服务提供方实现,服务提供方将自己jar包META-I ...

  9. java 中Map 使用

    Map用于保存具有映射关系的数据,Map里保存着两组数据:key和value,它们都可以使任何引用类型的数据,但key不能重复.所以通过指定的key就可以取出对应的value.Map接口定义了如下常用 ...

  10. cpci热插拔信号

    cpci热插拔信号1 BD_SEL#信号.对外围板是输入,是个1对1信号,来自背板的热插拔控制电路输出.每一个槽一个独立信号.用于控制热插拔外围板的上电控制.不实现热插拔的在背板直接接地:2 HEAL ...