1:懒汉的设计模式,在第一次调用的时候才完成相关的初始化操作

懒汉式是典型的时间换空间,就是每次获取实例都会进行判断,看是否需要创建实例,浪费判断的时间。当然,如果一直没有人使用的话,那就不会创建实例,则节约内存空间

package com.xiaohao.test;

/**
* 使用懒汉模式创建一个单例模式
* @author lenovo
*
*/
public class Singleton {
private static Singleton instance=null;
/**
* 返回或者创建相关的单例实例
* @return
*/
public static synchronized Singleton getInstance(){//使用同步方法保证线程安全
if(instance==null){
instance=new Singleton();
}
return instance;
}
/**
* 一个私有的构造方法,使外部的对象不能new相关的实例,这个尤其要注意,一定要提供默认的私有化的方法去覆盖默认的构造方法

* 否则的话,如果用户直接去new一个对象的话,就无法保证单例了~~~
*/
private Singleton(){}
}

2:饿汉的设计模式,在初始化类的过程中就会完成相关实例的初始化,一般认为这种方式要更加安全些

饿汉式是典型的空间换时间,当类装载的时候就会创建类的实例,不管你用不用,先创建出来,然后每次调用的时候,就不需要再判断,节省了运行时间。

package com.xiaohao.test;

/**
* 使用饿汉模式创建一个单例 模式
* @author lenovo
*
*/
public class Singleton {

//这个内部的单例仅仅用于内部访问,在初始化相关类的时候,就完成了相关单例类的初始化
//同时使用final修饰符修饰,一旦初始化值之后,不允许修改相关的值,这样也就实现了系统中的唯一
private static final Singleton instance=new Singleton();

/**
* 返回或者创建相关的单例实例
* @return
*/
public static Singleton getInstance(){
return instance;
}

/**
* 一个私有的构造方法,使外部的对象不能new相关的实例,这个尤其要注意,一定要提供默认的私有化的方法去覆盖默认的构造方法

* 否则的话,如果用户直接去new一个对象的话,就无法保证单例了~~~
*/

private Singleton(){}

}

此外还有一个比较给力的实现单例的方式,推荐大家使用这种方式:

Google公司的工程师Bob Lee写的新的懒汉单例模式
public class Singleton {

/**
* 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例
* 没有绑定关系,而且只有被调用到时才会装载,从而实现了延迟加载。
*/

static class SingletonHolder {

/**
* 静态初始化器,由JVM来保证线程安全
*/

static Singleton instance = new Singleton();    
  }    
   
  public static Singleton getInstance() {    
    return SingletonHolder.instance;    
  }    
   

  
在加载singleton时并不加载它的内部类SingletonHolder,而在调用getInstance()时调用SingletonHolder时才加载SingletonHolder,从而调用singleton的构造函数,实例化singleton,从而达到lazy loading的效果。

3:双重锁的设计模式,实现在多线程下,相关性能的提高,尤其避免懒汉模式中,每次获取实例的时候都需要线程同步的问题

双重锁的主要目的是解决每次获取实例的时候都需要进行线程等待,只有在第一次实例化时,才启用同步机制,提高了性能。

提示:由于volatile关键字可能会屏蔽掉虚拟机中一些必要的代码优化,所以运行效率并不是很高。因此一般建议,没有特别的需要,不要使用。也就是说,虽然可以使用“双重检    查加锁”机制来实现线程安全的单例,但并不建议大量采用,可以根据情况来选用。

package com.xiaohao.test;

/**
* 使用双重锁模式创建一个单例模式
* @author lenovo
*
*/
public class Singleton {
private static Singleton instance=null;
/**
* 返回或者创建相关的单例实例
* @return
*/
public static Singleton getInstance(){
if(instance==null)
{
 synchronized (Singleton.class){//需要注意的是,这里锁住的是类,一旦加上这个类锁之后,所有和这个类相关的操作(包括这个类的所有属性和方法)都需要进行相关的等待

if(instance==null){

instance=new Singleton();

}
}
}
return instance;
}
/**
* 一个私有的构造方法,使外部的对象不能new相关的实例,这个尤其要注意,一定要提供默认的私有化的方法去覆盖默认的构造方法

* 否则的话,如果用户直接去new一个对象的话,就无法保证单例了~~~
*/
private Singleton(){}
}

}

这个方法表面上看起来很完美,你只需要付出一次同步块的开销,但它依然有问题。除非你声明instance变量时使用了volatile关键字。没有volatile修饰符,可能出现Java中的另一个线程看到个初始化了一半的instance的情况,但使用了volatile变量后,就能保证先行发生关系(happens-before relationship)。对于volatile变量_instance,所有的写(write)都将先行发生于读(read),在Java 5之前不是这样,所以在这之前使用双重检查锁有问题。现在,有了先行发生的保障(happens-before guarantee),你可以安全地假设其会工作良好。另外,这不是创建线程安全的单例模式的最好方法,你可以使用枚举实现单例模式,这种方法在实例创建时提供了内置的线程安全。另一种方法是使用静态持有者模式(static holder pattern),这种方式就是开始的饿汉模式,所以说饿汉模式相对来说比较安全一些。

package com.xiaohao.test;

/**
* 使用双重锁模式创建一个单例模式,双重锁模式下的进一步优化
* @author lenovo
*
*/
public class Singleton {
//注意这里面的volatile 这个关键字,它的主要作用是写(write)优于读(read),前提是jdk的版本要不低于jdk5.0
private volatile static Singleton instance=null;
/**
* 返回或者创建相关的单例实例
* @return
*/
public static Singleton getInstance(){
if(instance==null)
{
synchronized (Singleton.class){//需要注意的是,这里锁住的是类,一旦加上这个类锁之后,所有和这个类相关的操作(包括这个类的所有属性和方法)都需要进行相关的等待

if(instance==null){

instance=new Singleton();

}
}
}
return instance;
}
/**
* 一个私有的构造方法,使外部的对象不能new相关的实例,这个尤其要注意,一定要提供默认的私有化的方法去覆盖默认的构造方法

* 否则的话,如果用户直接去new一个对象的话,就无法保证单例了~~~
*/
private Singleton(){}
}

4:使用枚举实现单例模式,这种方法在实例创建时提供了内置的线程安全

package com.xiaohao.test;

/**
* 使枚举的方法创建一个单例类
* @author lenovo
*
*/
public enum Singleton {
INSTANCE;// 使用枚举类的方法创建一个单例,据说这是目前位置,无论是多线程还是,防止反射创建
//相关对象最有用的方法,推荐使用
}

单元素的枚举类型已经成为实现Singleton的最佳方法。用枚举来实现单例非常简单,只需要编写一个包含单个元素的枚举类型即可。使用enum关键字来实现单例模式的好处是这样非常简洁,并且无偿地提供了序列化机制,绝对防止多次实例化,即使是在面对复杂的序列化或者反射攻击的时候。使用枚举来实现单实例控制会更加简洁,而且无偿地提供了序列化机制,并由JVM从根本上提供保障,绝对防止多次实例化,是更简洁、高效、安全的实现单例的方式。——来自《Effective Java》

***知识补充(拷贝的)----针对谷歌那个工程师的方法:

 这个模式综合使用了Java的类级内部类和多线程缺省同步锁的知识,很巧妙地同时实现了延迟加载和线程安全。

  1.相应的基础知识

  •  什么是类级内部类?

  简单点说,类级内部类指的是,有static修饰的成员式内部类。如果没有static修饰的成员式内部类被称为对象级内部类。

  类级内部类相当于其外部类的static成分,它的对象与外部类对象间不存在依赖关系,因此可直接创建。而对象级内部类的实例,是绑定在外部对象实例中的。

  类级内部类中,可以定义静态的方法。在静态方法中只能够引用外部类中的静态成员方法或者成员变量。

  类级内部类相当于其外部类的成员,只有在第一次被使用的时候才被会装载。

  •  多线程缺省同步锁的知识

  大家都知道,在多线程开发中,为了解决并发问题,主要是通过使用synchronized来加互斥锁进行同步控制。但是在某些情况中,JVM已经隐含地为您执行了同步,这些情况下就不用自己再来进行同步控制了。这些情况包括:

  1.由静态初始化器(在静态字段上或static{}块中的初始化器)初始化数据时

  2.访问final字段时

  3.在创建线程之前创建对象时

  4.线程可以看见它将要处理的对象时

  2.解决方案的思路

  要想很简单地实现线程安全,可以采用静态初始化器的方式,它可以由JVM来保证线程的安全性。比如前面的饿汉式实现方式。但是这样一来,不是会浪费一定的空间吗?因为这种实现方式,会在类装载的时候就初始化对象,不管你需不需要。

  如果现在有一种方法能够让类装载的时候不去初始化对象,那不就解决问题了?一种可行的方式就是采用类级内部类,在这个类级内部类里面去创建对象实例。这样一来,只要

不使用到这个类级内部类,那就不会创建对象实例,从而同时实现延迟加载和线程安全。

****最后需要注意一点,上面除了使用枚举类的方法外,其它的方法都可以通过java的反射机制创建相关的对象,即使使用private 重写了相关的构造方法~~

单例模式总结(Java版)的更多相关文章

  1. 你真的会写单例模式吗-------Java实现

    转载: 你真的会写单例模式吗--Java实现 单例模式可能是代码最少的模式了,但是少不一定意味着简单,想要用好.用对单例模式,还真得费一番脑筋.本文对Java中常见的单例模式写法做了一个总结,如有错漏 ...

  2. 网页爬虫的设计与实现(Java版)

    网页爬虫的设计与实现(Java版)     最近为了练手而且对网页爬虫也挺感兴趣,决定自己写一个网页爬虫程序. 首先看看爬虫都应该有哪些功能. 内容来自(http://www.ibm.com/deve ...

  3. [转] 你真的会写单例模式吗——Java实现

    你真的会写单例模式吗——Java实现 原文:http://www.tuicool.com/articles/MBrUfy6 单例模式可能是代码最少的模式了,但是少不一定意味着简单,想要用好.用对单例模 ...

  4. pureMVC java版搭建流程

    转自:http://blog.csdn.net/sutaizi/article/details/6588004 pureMVC 是一个轻量级的框架 它在 flex中非常流行(和cairngorm差不多 ...

  5. ArcGIS Server 10 Java 版的Rest服务手动配置方法

    Java版的Manager中发布的服务默认只发布了该服务的SOAP接口,而REST接口需要用户在信息服务器,如Tomcat. Apache.WebLogic等中手工配置.由于在Java版的Server ...

  6. PetaPojo —— JAVA版的PetaPoco

    背景 由于工作的一些原因,需要从C#转成JAVA.之前PetaPoco用得真是非常舒服,在学习JAVA的过程中熟悉了一下JAVA的数据组件: MyBatis 非常流行,代码生成也很成熟,性能也很好.但 ...

  7. 【转载】java版打字练习软件

    网上找到一个java版的打字的游戏 import java.applet.Applet; import java.applet.AudioClip; import java.awt.Dimension ...

  8. 微博地址url(id)与mid的相互转换 Java版

    原理: 新浪微博的URL都是如:http://weibo.com/2480531040/z8ElgBLeQ这样三部分. 第一部分(绿色部分)为新浪微博的域名,第二部分(红色部分)为博主Uid,第三部分 ...

  9. JCEF3——谷歌浏览器内核Java版实现(一):使用jawt获取窗体句柄

    前言 最近一段时间研究谷歌浏览器内核.谷歌浏览器内核一直开源,并维护更新,它的开源项目中内核更新速度和Chrome浏览器版本更新进度一样!而且它不同于WebKit(值得一题的是谷歌浏览器已不使用Web ...

  10. Selenium关键字驱动测试框架Demo(Java版)

    Selenium关键字驱动测试框架Demo(Java版)http://www.docin.com/p-803493675.html

随机推荐

  1. uestc 1725 吴神数

    // 筛选法// 先求出 sqrt(1<<31)内的素数// 然后筛选出符合要求的数// 详情见代码注释// #pragma comment(linker, "/STACK:10 ...

  2. mount

    产品,平台,RS6000, pseries 软件版本, aix 当NFS在NFS客户端加载时,系统会问是使用 soft-mount 还是hard-mount, 它们之间有什么区别? 它们的区别在于当发 ...

  3. java web 学习三(Tomcat 服务器学习和使用2)

    一.打包JavaWeb应用 在Java中,使用"jar"命令来对将JavaWeb应用打包成一个War包,jar命令的用法如下:

  4. CodeForces 558E(计数排序+线段树优化)

    题意:一个长度为n的字符串(只包含26个小字母)有q次操作 对于每次操作 给一个区间 和k k为1把该区间的字符不降序排序 k为0把该区间的字符不升序排序 求q次操作后所得字符串 思路: 该题数据规模 ...

  5. bjfu1250 模拟

    这题貌似是蓝桥杯的一题改了个题面. 就是模拟啦,应该有比我的更简洁的方法. 我的方法是把所有的人(蚂蚁)按位置排完序以后从左往右看,每次有一个向左走的,就会把最左边的t出,这个变成向右中,同时,从左端 ...

  6. cocos2d-x知识巩固-基础篇(1)

    有段时间没有学习cocos2dx了,作为新人,自己觉得还是要稳扎稳打,一点点的去积累,梳理好每一个知识点,这样对自己的成长能够有一个更清晰的认识,以便做更好的提高. 从2013年8月开始接触cocos ...

  7. 将 Sublime 3 打造成 Python/Django IDE

    Sublime Text 是一款非常强大的文本编辑器, 下面我们介绍如何将 Sublime Text 3 打造成一款 Python/Django 开发利器: 1. 安装 Sublime Text 3 ...

  8. [HIve - LanguageManual] LateralView

    Lateral View Syntax Description Example Multiple Lateral Views Outer Lateral Views Lateral View Synt ...

  9. Bmob第三方登录详解

    Bmob第三方登录详解 Bmob 第三方登录 简介 本文主要介绍新浪微博,QQ,微信的登录接入以及如何配合BmobSDK中的第三方登录功能实现第三方登录. 在使用之前请先按照快速入门创建好可以调用Bm ...

  10. SRM 502 DIV1 500pt(DP)

    题目简述 给定比赛时间T和n个题目,你可以在任意时间提交题目,每个题目有一个初始分数maxPoints[i],每个单位时间题目的分数将会减少pointsPerMinute[i],即如果在时间t解决了第 ...