JAVA实现单例模式的四种方法和一些特点
一、饿汉式单例类
{
private Singleton(){
}
private static Singleton
instance = new Singleton();
private static Singleton
getInstance(){
return instance;
}
}
特点:饿汉式提前实例化,没有懒汉式中多线程问题,但不管我们是不是调用getInstance()都会存在一个实例在内存中
二、内部类式单例类
代码如下:
{
private Singleton(){
}
private class
SingletonHoledr(){
private static Singleton instance = new
Singleton();
}
private static Singleton
getInstance(){
return SingletonHoledr.instance;
}
}
特点:内部类式中,实现了延迟加载,只有我们调用了getInstance(),才会创建唯一的实例到内存中.并且也解决了懒汉式中多线程的问题.解决的方式是利用了Classloader的特性.
三、懒汉式单例类
代码如下:
{
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都为空,这样就会生成两个实例。解决的办法是同步:
可以同步但是效率不高:
代码如下:
{
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的时候,根本不需要线程同步。
于是聪明的人们想出了下面的做法:
双检锁写法:
代码如下:
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实现单例模式的四种方法和一些特点的更多相关文章
- 【Java】详解Java解析XML的四种方法
XML现在已经成为一种通用的数据交换格式,平台的无关性使得很多场合都需要用到XML.本文将详细介绍用Java解析XML的四种方法. AD: XML现在已经成为一种通用的数据交换格式,它的平台无关性,语 ...
- java环境变量配置四种方法
原文:java环境变量配置四种方法 Java编程首要工作就是安装JDK(Java Development Kit).一通“NEXT”点完安装后就是最重要的环境变量设置了.也许有人会问为什么要设置环境变 ...
- Java解析XML的四种方法详解 - 转载
XML现在已经成为一种通用的数据交换格式,平台的无关性使得很多场合都需要用到XML.本文将详细介绍用Java解析XML的四种方法 在做一般的XML数据交换过程中,我更乐意传递XML字符串,而不是格式化 ...
- java中定时器的四种方法
package com.lid; import java.util.Calendar; import java.util.Date; import java.util.Timer; import ja ...
- java 遍历map的四种方法
16:21:42 Map.entrySet() 这个方法返回的是一个Set<Map.Entry<K,V>>,Map.Entry 是Map中的一个接口,他的用途是表示一个映射项( ...
- Java实现单例模式的9种方法
一. 什么是单例模式 因程序需要,有时我们只需要某个类同时保留一个对象,不希望有更多对象,此时,我们则应考虑单例模式的设计. 二. 单例模式的特点 1. 单例模式只能有一个实例. 2. 单例类必须创建 ...
- Python单例模式的四种方法
在这之前,先了解super()和__new__()方法 super()方法: 返回一个父类或兄弟类类型的代理对象,让你能够调用一些从继承过来的方法. 它有两个典型作用: a. 在单继承的类层次结构中, ...
- java创建线程的四种方法
第一种: 通过继承Thread类创建线程 第二种: 通过实现Runnable接口创建线程 这两种早已烂记于心,这里就不作过多的介绍, 主要介绍其源码 Thread类 implements Runna ...
- Java中创建对象的四种方法
第一种 使用new关键字 第二种 使用反射技术:1)通过Class类的newInstance()方法:2)通过Constructor类的newInstance方法 第三种 通过Object类的clon ...
随机推荐
- Django安装数据库MySQLdb
在使用Django搭建与树莓派智能终端时,使用mysql作为数据库管理,遇到如下问题: django.core.exceptions.ImproperlyConfigured: Error loadi ...
- Services: ARP Caching
Online Help for Cisco IOS Release 12.2(15)JA Services: ARP Caching ARP caching on the access point ...
- ubuntu 16.04 XDRP实现Windows远程访问
如何通过XDRP实现Windows远程访问 下面才是本文的重点,本文主要是讲xrdp在目前最新版Ubuntu 16.04下,如果实现Windows远程访问.网上也很多相关教程,但是都需要安装xfac4 ...
- 前端学习 之 JavaScript DOM 与 BOM
一. DOM介绍 1. 什么是DOM? DOM:文档对象模型.DOM 为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构. 目的其实就是为了能让js操作html元素而制定的一个规范. DOM就 ...
- Mac旧机「焕」新机过程记录
一.首先我做了非硬件上的优化处理,在升级到10.14之前还是挺管用的.但是为了使用最新的iOS SDK,升级到10.14以后,已经不管用了. 1.设置->通用 将动画相关的选项去掉. 2.设置- ...
- 第五周之Hadoop学习(五)
在上周已经完成Hadoop的Java编程环境下的配置,这周则是通过对Eclipse的环境编程对Hadoop的API进行简单的调用 参考地址:https://blog.csdn.net/u0105237 ...
- 8 HTML DOM 元素的查找与改变&改变CSS样式&HTML事件
HTML DOM(Document Object Model)文档对象模型 当网页被加载时,浏览器会创建页面的文档对象模型. HTMLDOM 定义了用于HTML的一系列标准的对象.通过DOM,你可以访 ...
- Unity初步 基本拼图实现
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; ...
- Java基础 -4
IF分支结构 在程序开发的过程中 一共会存在有三组程序逻辑:顺序结构.分支结构.循环结构 if分支结构主要是针对关系表达式进行判断处理的分支操作. if判断 public static void ma ...
- Manacher(马拉车)算法
Manacher算法是一个求字符串的最长回文子串一种非常高效的方法,其时间复杂度为O(n).下面分析以下其实行原理及代码: 1.首先对字符串进行预处理 因为回文分为奇回文和偶回文,分类处理比较麻烦,所 ...