java 设计模型之单例模式详解

Singleton 模式的宗旨在于确保某个类只有一个实例,别且为之提供一个全局访问点。为了防止其他工作人员实例化我们的类,

可以为该类创建唯一一个构造器,并将构造器的可见设置为私有。值得注意的是,如果我们创建了其他的非私有的构造器,或者根本没有为该类提

供构造器,那么其他人员还是能实例化我们的类。 如果不希望提前创建单例对象,我们可以等到第一次使用该单例对象的时候在创建它,即

滞后初始化。滞后初始化单例对象有两个理由:

1.也许在静态初始化时间,你没有关于如何初始化单例对象的足够信息。

2.选择滞后初始化单例的目的也许为了等待资源,诸如数据库连接,尤其是在某些特定会话中不需要这个单例的应用程序中。
  如果在多线程环境中对单例采用滞后初始化,那么我们必须小心防止多个线程同时初始化该

通常单例模式在Java语言中,有两种构建方式:

懒汉方式:指全局的单例实例在第一次被使用时构建。延迟初始化。

饿汉方式:指全局的单例实例在类装载时构建。 急切初始化。

1,饿汉式单例类

public class Singleton1 {

 private Singleton1() {
 }
 // 在自己内部定义自己一个实例.
 // 注意这是private 只供内部调用

 private static Singleton1 instance = new Singleton1();

 /** *//**
 * 这里提供了一个供外部访问本class的静态方法,可以直接访问  
 * @return
 */
 public static Singleton1 getInstance() {
 return instance;
 }
}

2,懒汉式单例类

public class Singleton2 {

 private static Singleton2 instance = null;
 /** *//**
 * 这个方法比上面有所改进,不用每次都进行生成对象,只是第一次   
 * 使用时生成实例,提高了效率!
 * @return
 */
 public static Singleton2 getInstance() {
 if (instance == null)
 instance = new Singleton2();
 return instance;
 }
}

下面主要多线程问题,在懒汉单例中,单线程是没有问题的,但多线程时就会有可能出现两个或者以上的Singletion2实例的情况。

例如:线程1在判断instance==null为真,扫行new操作时,在执行new操作之前,判断为真之后,线程2正好执行判断操作,这时instance还为null.因此,线程2也会执行new操作。以此类推,在高并发下面,就可能存在两个或者以上的Singletion2的实例。显然,这是不正确的。

因此改变代码如下:

public class Singleton3 {

 private static Singleton3 instance = null;
 /** *//**
 * 这个方法比上面有所改进,不用每次都进行生成对象,只是第一次   
 * 使用时生成实例,提高了效率!
 * 为了多线程不出错,加入了同步标志
 * @return
 */
 public static synchronized Singleton3 getInstance() {
 if (instance == null)
 instance = new Singleton3();
 return instance;
 }

}

但这样又产生了一个问题,每次获取实例时方法都是同步的,显然性能很受影响的,所以继续更改代码如下:

volatile, 用更低的代价替代同步

为什么使用volatile比同步代价更低?
同步的代价, 主要由其覆盖范围决定, 如果可以降低同步的覆盖范围, 则可以大幅提升程序性能.

而volatile的覆盖范围仅仅变量级别的. 因此它的同步代价很低.

volatile原理是什么?

volatile的语义, 其实是告诉处理器, 不要将我放入工作内存, 请直接在主存操作我.(工作内存详见java内存模型)

因此, 当多核或多线程在访问该变量时, 都将直接操作主存, 这从本质上, 做到了变量共享.

volatile的有什么优势?
1, 更大的程序吞吐量
2, 更少的代码实现多线程
3, 程序的伸缩性较好
4, 比较好理解, 无需太高的学习成本

volatile有什么劣势?
1, 容易出问题
2, 比较难设计

volatile使用jdk要求1.5版本及1.5以上。

改进后的代码如下(又叫双重加锁):

public class Singleton4 {
 private static volatile Singleton4 instance;
 /** *//**
 * 双重加锁实现多线程运用和性能优化
 * @return
 */
 public static Singleton4 getInstance()
 {
 if (instance == null)
 {
 synchronized(Singleton4.class) { //1
 if (instance == null) //2
 instance = new Singleton4(); //3
 }
 }
 return instance;
 }
}
(0)

相关推荐

  • Java单例模式实例简述

    本文实例讲述了Java的单例模式,是Java程序设计中非常重要的概念.分享给大家供大家参考.具体分析如下: 所谓单子模式就是在整个应用过程中只向外界提供唯一的一份实例,也就是说在应用时只有一个实例,这样也就不用反反复复的创建实例了.那么根据他的要求,看下面一个最简单的单例模式的代码: public class Singleton { private static Singleton single = new Singleton(); private Singleton(){ } public s

  • java单例模式使用及注意事项

    1. 说明 1)单例模式:确保一个类只有一个实例,自行实例化并向系统提供这个实例 2)单例模式分类:饿单例模式(类加载时实例化一个对象给自己的引用),懒单例模式(调用取得实例的方法如getInstance时才会实例化对象)(java中饿单例模式性能优于懒单例模式,c++中一般使用懒单例模式) 3)单例模式要素: a)私有构造方法b)私有静态引用指向自己实例c)以自己实例为返回值的公有静态方法 2.实例 饿单例模式: 复制代码 代码如下: package com.wish.modedesign;

  • Java单例模式的应用示例

    单例模式用于保证在程序的运行期间某个类有且仅有一个实例.其优势在于尽可能解决系统资源.通过修改构造方法的访问权限就可以实现单例模式. 代码如下: 复制代码 代码如下: public class Emperor {    private static Emperor emperor = null;// 声明一个Emperor类的引用 private Emperor() {// 将构造方法私有    } public static Emperor getInstance() {// 实例化引用   

  • java单例模式4种使用方式分享

    1.Java Concurrency In Practice的List 复制代码 代码如下: public class Singleton {      private static class SingletonHolder {          public static Singleton resource = new Singleton();      }      public static Singleton getResource() {          return  Sing

  • 浅析Java设计模式编程中的单例模式和简单工厂模式

    单例模式 动机 有时候只有一个类的实例是很重要的.比如,一个系统应该只有一个窗口管理实例. 单例模式是最简单设计模式:类负责实例化自己,确保只有一个实例,并且提供一个访问这个实例的入口. 目的 1. 确保只有一个实例被创建. 2. 提供访问这个实例的入口. 使用final确保被创建一次,private的构造函数确保不被实例化.public的getInstance方法确保外部能够访问.下面是饿汉模式: public class Singleton { private static final Si

  • java单例模式使用详解

    单例模式想必大家都已经很熟悉了,通常它的实现方式分为以下两种: 复制代码 代码如下: //懒汉式实现public class Singleton{    private static Singleton instance = null;        private Singleton(){}    public static newInstance(){        if(null == instance){            instance = new Singleton();   

  • Java单例模式、饥饿模式代码实例

    class MyThreadScopeData {       // 单例     private MyThreadScopeData() {     }       // 提供获取实例方法     public static synchronized MyThreadScopeData getThreadInstance() {         // 从当前线程范围内数据集中获取实例对象         MyThreadScopeData instance = map.get();      

  • java多线程之线程安全的单例模式

    概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建自己的唯一实例. 3.单例类必须给所有其他对象提供这一实例. 单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例.在计算机系统中,线程池.缓存.日志对象.对话框.打印机.显卡的驱动程序对象常被设计成单例.这些应用都或多或少具有资源管理器的功能.每台计算机可以有若干个打印机,但只能有一个Printer

  • java设计模式之单例模式学习

    1 概述 单例模式有几个好处: (1)某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销. (2)省去了new操作符,降低了系统内存的使用频率,减轻GC压力. (3)有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了. 2 详解 单例模式常用的写法有如下这么两种. 2.1 饿汉式 如果应用程序总是创建并使用单例模式,或者在创建和运行时压力不是很大的情况下,可以使用一个私有静态变量,提前把对象创建好. 复制代码 代码如下: package org.sc

  • java 设计模型之单例模式详解

    Singleton 模式的宗旨在于确保某个类只有一个实例,别且为之提供一个全局访问点.为了防止其他工作人员实例化我们的类, 可以为该类创建唯一一个构造器,并将构造器的可见设置为私有.值得注意的是,如果我们创建了其他的非私有的构造器,或者根本没有为该类提 供构造器,那么其他人员还是能实例化我们的类. 如果不希望提前创建单例对象,我们可以等到第一次使用该单例对象的时候在创建它,即 滞后初始化.滞后初始化单例对象有两个理由: 1.也许在静态初始化时间,你没有关于如何初始化单例对象的足够信息. 2.选择

  • Java开发中为什么要使用单例模式详解

    一.什么是单例模式? 单例设计模式(Singleton Design Pattern)理解起来非常简单.一个类只允许创建一个对象(或者实例),那这个类就是一个单例类,这种设计模式就叫作单例设计模式,简称单例模式. 二.实战案例一:处理资源访问冲突 我们先来看第一个例子.在这个例子中,我们自定义实现了一个往文件中打印日志的 Logger 类.具体的代码实现如下所示: public class Logger { private FileWriter writer; public Logger() {

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

    单例模式的特点 一个类只允许产生一个实例化对象. 单例类构造方法私有化,不允许外部创建对象. 单例类向外提供静态方法,调用方法返回内部创建的实例化对象.  懒汉式(线程不安全) 其主要表现在单例类在外部需要创建实例化对象时再进行实例化,进而达到Lazy Loading 的效果. 通过静态方法 getSingleton() 和private 权限构造方法为创建一个实例化对象提供唯一的途径. 不足:未考虑到多线程的情况下可能会存在多个访问者同时访问,发生构造出多个对象的问题,所以在多线程下不可用这种

  • Django中的模型类设计及展示示例详解

    django中设计数据模型类是基于ORM的对象关系映射更方便的进行数据库中的数据操作. 对象关系映射 把面向对象中的类和数据库表--对应,通过操作类和对象,对数表实现数据操作,不需要写sql,由ORM框架生成 django实现了ORM框架,在项目中与数据库之间产生桥梁作用 django数据库定义模型的步骤如下: python manage.py makemigrations python mange.py migrate 在应用models.py中编写模型类,继承models.Model类 在模

  • java基面试础知识详解

    面向对象的三大特性 1)封装 就是把同一类事物的属性和方法归到同一个类中,方便使用 防止该类的代码和数据被外部类定义的代码随意访问 要访问该类的数据和代码必须通过严格的方法控制 封装的主要功能在于我们能修改自己的实现代码,而不用修改哪些调用程序的代码片段. 优点:减少耦合,类内部自由修改,可以对类成员变量进行更精确的控制,隐藏信息.实现细节. 最佳实践: 为了实现良好的封装,通常将类的成员变量声明为private ,通过public的set和get方法完成对属性的操作 2)继承 继承就是子类继承

  • Java之JSF框架案例详解

    这是一个分为两部分的系列,其中我介绍了JSF 2及其如何适合Java EE生态系统. 在第1部分中,我将介绍JavaServer Pages(JSF)背后的基本思想 ,在第2部分中,将介绍Facelets声明语言 . 在构建Web应用程序时,我们为最终用户提供了一种与我们的应用程序进行交互的方式,这就是JSF所提供的. 我将向您介绍MVC设计模式以及如何使用它,并且您将发现Facelets视图语言及其使用方式,如何将数据和事件绑定到上下文以及如何通过表达语言来实现. 我将通过查看替代模板框架(例

  • Java多线程编程综合案例详解

    目录 Java多线程综合案例 数字加减 生产电脑 竞争抢答 Java多线程综合案例 数字加减 设计4个线程对象,两个线程执行减操作,两个线程执行加操作 public class ThreadDemo{ public static void main(String[] args) throws Exception { Resource res=new Resource(); AddThread at=new AddThread(res); SubThread st=new SubThread(re

  • Spring jdbc中数据库操作对象化模型的实例详解

    Spring jdbc中数据库操作对象化模型的实例详解 Spring Jdbc数据库操作对象化 使用面向对象方式表示关系数据库的操作,实现一个线程安全可复用的对象模型,其顶级父类接口RdbmsOperation. SqlOperation继承该接口,实现数据库的select, update, call等操作. 1.查询接口:SqlQuery 1) GenericSqlQuery, UpdatableSqlQuery, MappingSqlQueryWithParameter 2) SqlUpda

  • Java 反射机制的实例详解

    Java 反射机制的实例详解 前言 今天介绍下Java的反射机制,以前我们获取一个类的实例都是使用new一个实例出来.那样太low了,今天跟我一起来学习学习一种更加高大上的方式来实现. 正文 Java反射机制定义 Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 用一句话总结就是反射可以实现在运行时可以知道任意一个类的属性和方法. 反射

  • Java枚举的使用方法详解

     Java枚举的使用方法详解 前言  你代码中的flag和status,都应该用枚举来替代 很多人都说,枚举在实际开发中很少用到,甚至就没用到.因为,他们的代码往往是这样子的: public class Constant { /* * 以下几个变量表示英雄的状态 */ public final static int STATUS_WALKING = 0;//走 public final static int STATUS_RUNNINGING = 1;//跑 public final stati

随机推荐