JAVA实现单例模式的四种方法和一些特点,需要的朋友可以参考一下
 
 

一、饿汉式单例类

复制代码 代码如下:
public class Singleton 

   
private Singleton(){

}

private static Singleton
instance = new Singleton();

private static Singleton
getInstance(){ 
        return instance; 
    } 
}

特点:饿汉式提前实例化,没有懒汉式中多线程问题,但不管我们是不是调用getInstance()都会存在一个实例在内存中

二、内部类式单例类

复制代码
代码如下:
public class Singleton    
{       

        private Singleton(){

}

private class
SingletonHoledr(){    
        private static Singleton instance = new
Singleton();    
    }

private static Singleton
getInstance(){    
        return SingletonHoledr.instance;    
   
}    
}

特点:内部类式中,实现了延迟加载,只有我们调用了getInstance(),才会创建唯一的实例到内存中.并且也解决了懒汉式中多线程的问题.解决的方式是利用了Classloader的特性.

三、懒汉式单例类

复制代码
代码如下:
public class Singleton    
{       

    private Singleton(){

}

private static
Singleton instance;    
    public static Singleton getInstance(){    

        if(instance == null){    
            return instance = new
Singleton();    
        }else{    
            return instance;    

        }    
    }    
}  

特点:在懒汉式中,有线程A和B,当线程A运行到第8行时,跳到线程B,当B也运行到8行时,两个线程的instance都为空,这样就会生成两个实例。解决的办法是同步:

可以同步但是效率不高:

复制代码
代码如下:
public class Singleton    
{       

    private Singleton(){

}

private static
Singleton instance;    
    public static synchronized Singleton
getInstance(){    
        if(instance == null){    
            return
instance = new Singleton();    
        }else{    
            return
instance;    
        }    
    }    
}

这样写程序不会出错,因为整个getInstance是一个整体的"critical
section",但就是效率很不好,因为我们的目的其实只是在第一个初始化instance的时候需要locking(加锁),而后面取用instance的时候,根本不需要线程同步。

于是聪明的人们想出了下面的做法:

双检锁写法:

复制代码
代码如下:
public class Singleton{ 
  private
static Singleton single;    //声明静态的单例对象的变量 
  private Singleton(){}   
//私有构造方法

public static Singleton getSingle(){    //外部通过此方法可以获取对象   

    if(single == null){    
        synchronized (Singleton.class) {  
//保证了同一时间只能只能有一个对象访问此同步块       
            if(single == null){     

                single = new Singleton();         
        }    

      } 
    }   
    return single;   //返回创建好的对象  
  } 
}

思路很简单,就是我们只需要同步(synchronize)初始化instance的那部分代码从而使代码既正确又很有效率。

这就是所谓的“双检锁”机制(顾名思义)。
很可惜,这样的写法在很多平台和优化编译器上是错误的。

原因在于:instance = new Singleton()这行代码在不同编译器上的行为是无法预知的。一个优化编译器可以合法地如下实现instance
= new Singleton():

1. instance  = 给新的实体分配内存

2. 调用Singleton的构造函数来初始化instance的成员变量

现在想象一下有线程A和B在调用getInstance,线程A先进入,在执行到步骤1的时候被踢出了cpu。然后线程B进入,B看到的是instance 
已经不是null了(内存已经分配),于是它开始放心地使用instance,但这个是错误的,因为在这一时刻,instance的成员变量还都是缺省值,A还没有来得及执行步骤2来完成instance的初始化。

当然编译器也可以这样实现:

1. temp = 分配内存

2. 调用temp的构造函数

3. instance = temp

如果编译器的行为是这样的话我们似乎就没有问题了,但事实却不是那么简单,因为我们无法知道某个编译器具体是怎么做的,因为在Java的memory
model里对这个问题没有定义。

双检锁对于基础类型(比如int)适用。很显然吧,因为基础类型没有调用构造函数这一步。

JAVA实现单例模式的四种方法和一些特点的更多相关文章

  1. 【Java】详解Java解析XML的四种方法

    XML现在已经成为一种通用的数据交换格式,平台的无关性使得很多场合都需要用到XML.本文将详细介绍用Java解析XML的四种方法. AD: XML现在已经成为一种通用的数据交换格式,它的平台无关性,语 ...

  2. java环境变量配置四种方法

    原文:java环境变量配置四种方法 Java编程首要工作就是安装JDK(Java Development Kit).一通“NEXT”点完安装后就是最重要的环境变量设置了.也许有人会问为什么要设置环境变 ...

  3. Java解析XML的四种方法详解 - 转载

    XML现在已经成为一种通用的数据交换格式,平台的无关性使得很多场合都需要用到XML.本文将详细介绍用Java解析XML的四种方法 在做一般的XML数据交换过程中,我更乐意传递XML字符串,而不是格式化 ...

  4. java中定时器的四种方法

    package com.lid; import java.util.Calendar; import java.util.Date; import java.util.Timer; import ja ...

  5. java 遍历map的四种方法

    16:21:42 Map.entrySet() 这个方法返回的是一个Set<Map.Entry<K,V>>,Map.Entry 是Map中的一个接口,他的用途是表示一个映射项( ...

  6. Java实现单例模式的9种方法

    一. 什么是单例模式 因程序需要,有时我们只需要某个类同时保留一个对象,不希望有更多对象,此时,我们则应考虑单例模式的设计. 二. 单例模式的特点 1. 单例模式只能有一个实例. 2. 单例类必须创建 ...

  7. Python单例模式的四种方法

    在这之前,先了解super()和__new__()方法 super()方法: 返回一个父类或兄弟类类型的代理对象,让你能够调用一些从继承过来的方法. 它有两个典型作用: a. 在单继承的类层次结构中, ...

  8. java创建线程的四种方法

    第一种:  通过继承Thread类创建线程 第二种: 通过实现Runnable接口创建线程 这两种早已烂记于心,这里就不作过多的介绍, 主要介绍其源码 Thread类 implements Runna ...

  9. Java中创建对象的四种方法

    第一种 使用new关键字 第二种 使用反射技术:1)通过Class类的newInstance()方法:2)通过Constructor类的newInstance方法 第三种 通过Object类的clon ...

随机推荐

  1. 28 JavaScript语言类型&运算符

    语言类型: 弱类型:可以改变变量值和对象类型 强类型:可以改变变量值不能改变对象类型 解释型:边编译边执行,速度慢.解释型一般是弱类型 编译型:先编译再执行(C++\Java),速度快.编译型一般是强 ...

  2. replace() 方法用在字符串中用一些字符替换另一些字符实例

    后台给返回的格式是这样的 控制台打印出来格式是这样的 现在需要将这个字符串的数据显示在界面上,1-网站:2-APP:3-客户端 for(var i = 0; i < list.length; i ...

  3. 洛谷P1073最优贸易(跑两遍dij)

    题目描述 CC C国有n n n个大城市和m mm 条道路,每条道路连接这 nnn个城市中的某两个城市.任意两个城市之间最多只有一条道路直接相连.这 mmm 条道路中有一部分为单向通行的道路,一部分为 ...

  4. 刷题17. Letter Combinations of a Phone Number

    一.题目说明 题目17. Letter Combinations of a Phone Number,题目给了下面一个图,输入一个字符串包括2-9,输出所有可能的字符组合. 如输入23所有可能的输出: ...

  5. 2019年5月6日A股两百点暴跌行情思考

    原因:特朗普推特发布贸易战消息 盘面:跳空低开,单边下跌,上证指数最大跌幅200点,收盘千股跌停 操作:开盘加仓,盘中加仓,尾盘满仓 总结: 特大黑天鹅事件爆发引发大盘暴跌时,后续必将迎来一个反弹机会 ...

  6. GitHub 网站汉化

    居然是一个中文Github网站!该不会是个假的吧? 2018-09-03 17:30 前几天分享了一篇文章——3个搜索技巧!在 GitHub上快速找到实用资源!眼尖心细的读者发现了文中的Github网 ...

  7. C语言程序编译

    原来GCC的含义是GNU C Compiler,当初知识编译C语言,而现在GCC不知编译C语言,除此之外它还支持编译Ada.C++.Java.Object C.Pascal.COBOL.等等许多语言, ...

  8. keil条件断点

    http://www.keil.com/support/man/docs/uv4/uv4_db_dbg_breakpnts.htm Target Device does not support con ...

  9. 第1节 Scala基础语法:1、2、概述,什么是scala

    Scala编程 1.    课程目标 1.1.  目标1:熟练使用scala编写Spark程序 1.2.  目标2:动手编写一个简易版的Spark通信框架 1.3.  目标3:为阅读Spark内核源码 ...

  10. Android Studio的HAXM不支持虚拟机

    因为我的计算机是服务器,不支持虚拟机,所以报这个错了. 解决方式是直接连接物理手机,打开USB调试,安装驱动,运行项目即可.