java 设计模型之单例模式详解_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;
 }
}

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索java
, 单例模式
, singleton
设计模型
java单例模式详解、单例模式详解、单例设计模式详解、php单例模式详解、java单例模式,以便于您获取更多的相关知识。

时间: 2024-10-28 07:53:12

java 设计模型之单例模式详解_java的相关文章

5种Java经典创建型模式详解_java

一.概况 总体来说设计模式分为三大类: (1)创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. (2)结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模式.享元模式. (3)行为型模式,共十一种:策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释器模式. 二.设计模式的六大原则 1.开闭原则(Open Close Principle) 开闭原则就是说对扩展开放,对修

基于Java中字符串内存位置详解_java

前言 之前写过一篇关于JVM内存区域划分的文章,但是昨天接到蚂蚁金服的面试,问到JVM相关的内容,解释一下JVM的内存区域划分,这部分答得还不错,但是后来又问了Java里面String存放的位置,之前只记得String是一个不变的量,应该是要存放在常量池里面的,但是后来问到new一个String出来应该是放到哪里的,这个应该是放到堆里面的,后来又问到String的引用是放在什么地方的,当时傻逼的说也是放在堆里面的,现在总结一下:基本类型的变量数据和对象的引用都是放在栈里面的,对象本身放在堆里面,

Java中Properties的使用详解_java

Java中有个比较重要的类Properties(Java.util.Properties),主要用于读取Java的配置文件,各种语言都有自己所支 持的配置文件,配置文件中很多变量是经常改变的,这样做也是为了方便用户,让用户能够脱离程序本身去修改相关的变量设置.今天,我们就开始Properties的使用. Java中Properties的使用 Properties的文档说明: The Properties class represents a persistent set of propertie

Java静态方法不具有多态性详解_java

动态绑定机制使得基类的引用能够指向正确的子类对象,从而使得面向基类编程成为可能. 然而动态绑定在以下两种情况会失效. 1.基类方法是private或final修饰的 这个很好理解,因为private说明该方法对子类是不可见的,子类再写一个同名的方法并不是对父类方法进行复写(Override),而是重新生成一个新的方法,也就不存在多态的问题了.同理也可以解释final,因为方法同样是不可覆盖的. 2.方法是static修饰的 代码如下所示. class Base { public static v

Java中单例模式详解_java

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

Java设计模式之策略模式详解_java

本文实例为大家分享了Java策略模式,供大家参考,具体内容如下 1.策略模式(Strategy Pattern)是一种比较简单的模式,也叫做政策模式(PolicyPattern). 定义如下: Define a family of algorithms,encapsulate each one,and make them interchangeable.    (定义一组算法,将每个算法都封装起来,并且使它们之间可以互换.) 策略模式的通用类图如下所示: 策略模式的三个角色: ● Context

java equals和==的区别详解_java

大概说equals和==都比较的是什么: 1. boolean tem = a == b; 首先==比较的肯定是地址,从堆栈的角度说也就是说==比较的是栈上面的内容.因为栈是用来存放地址或是java中八大基本类型中自动变量的字面值(自动变量就是用int a = 1;这种形式来定义的变量).如果是自动变量比较值的话肯定是用==来比较,因为equals()是一个方法,所以必须由对象调用才可以用于比较.而自动变量既不是类的实例也不是类的引用所以不能用equals()方法. 2.boolean tem

Java中Map的排序问题详解_java

Map的种类 在Java中,Map的主要作用是存储键值对.由于是根据键得到值,所以不允许键重复.它主要有如下几个类别: HashMap: 最常用的Map,它根据键的HashCode值存储数据,根据键可以直接获取它的值,具有很快的访问速度,遍历时,取得数据的顺序是完全随机的.HashMap最多只允许一条记录的键为Null;允许多条记录的值为Null;HashMap不支持线程的同步,即任一时刻可以有多个线程同时写HashMap;可能会导致数据的不一致.如果需要同步,可以用Collections的sy

Java中JSON字符串与java对象的互换实例详解_java

在开发过程中,经常需要和别的系统交换数据,数据交换的格式有XML.JSON等,JSON作为一个轻量级的数据格式比xml效率要高,XML需要很多的标签,这无疑占据了网络流量,JSON在这方面则做的很好,下面先看下JSON的格式, JSON可以有两种格式,一种是对象格式的,另一种是数组对象, {"name":"JSON","address":"北京市西城区","age":25}//JSON的对象格式的字符串 [