在学习单例模式前,不妨问自己几个问题:单例模式是怎么来的,单例模式怎么去用?

单例模式是怎么来的?

这就从设计模式起源开始,他是在实际实践中遇到类似情况可以通用经验所得到的总结,一般在其他模块或者方法多次调用类对象,也就是公共模块,用单例模式可以减少内存的消耗。

单例模式怎么去用?

那这个容易,然后很快不到一分钟写完了。

 public class singleTonEx01 {

     private static singleTonEx01 singleTon;

     public static void main(String args[]) {
singleTonEx01 test1=singleTonEx01.getInstance();
test1.CommonMethod();
} // 防止使用new构造函数实例化对象
private singleTonEx01() { } public static singleTonEx01 getInstance() {
if(null==singleTon)
singleTon=new singleTonEx01();
return singleTon;
} public void CommonMethod() {
System.out.println(getClass().getName());
} }

但这里会有问题,啥问题呢?单线程中是没问题,但是多线程会出现问题,假设两个多线程A与B,A与B同时判断singleTon不为空,那会创建两次,那对于这个问题需要使用同步锁去解决了,下面改造下代码。

public class singleTonEx01 {

    private static singleTonEx01 singleTon;

    public static void main(String args[]) {
singleTonEx01 test1 = singleTonEx01.getInstance();
test1.CommonMethod();
} // 防止使用new构造函数实例化对象
private singleTonEx01() { } public static singleTonEx01 getInstance() {
synchronized (singleTonEx01.class) {
if (null == singleTon)
singleTon = new singleTonEx01();
}
return singleTon;
} public void CommonMethod() {
System.out.println(getClass().getName());
} }

这还不是最好的方法,如果是这样的话每个线程都会使用同步锁代码块,使用同步锁其实是消耗资源的,因此,可以再改进下,在外面锁再加个判断,这样一来提高了效率。(推荐这种写法1)

另外,补充一下,实例变量加上volatile的意义。

创建对象可以分解为如下的3行伪代码memory=allocate(); //1:分配对象的内存空间ctorInstance(memory); //2:初始化对象instance=memory; //3:设置instance指向刚分配的内存地址上面3行代码中的2和3之间,可能会被重排序导致先3后2;

public class singleTonEx01 {

    private volatile static singleTonEx01 singleTon;

    public static void main(String args[]) {
singleTonEx01 test1 = singleTonEx01.getInstance();
test1.CommonMethod();
} // 防止使用new构造函数实例化对象
private singleTonEx01() { } public static singleTonEx01 getInstance() {
if (singleTon == null) {
synchronized (singleTonEx01.class) {
if (null == singleTon)
singleTon = new singleTonEx01();
}
}
return singleTon;
} public void CommonMethod() {
System.out.println(getClass().getName());
} }

其实还有另外两种方法,一种是不管有没有调用都实例化(俗称恶汉式),另一种是静态内部类的方法(推荐这种写法2),线程安全而且高效

public class singleTonEx02 {

    private   static final singleTonEx02 singleTon=new singleTonEx02();

    public static void main(String args[]) {
singleTonEx02 test1 = singleTon;
test1.CommonMethod();
} // 防止使用new构造函数实例化对象
private singleTonEx02() { } public static singleTonEx02 getIntance() {
return singleTon;
} public void CommonMethod() {
System.out.println(getClass().getName());
} }
public class singleTonEx03 {

    private static class SingleNBClass {

        private final static singleTonEx03 singleTonEx03=new singleTonEx03();

    }

    public static void main(String args[]) {
singleTonEx03 test1 = singleTonEx03.getIntance();
test1.CommonMethod();
} // 防止使用new构造函数实例化对象
private singleTonEx03() { } public static final singleTonEx03 getIntance() {
return SingleNBClass.singleTonEx03;
} public void CommonMethod() {
System.out.println(getClass().getName());
} }

Easy单例模式的更多相关文章

  1. java设计模式(二)单例模式 建造者模式

    (三)单例模式 单例模式应该是最常见的设计模式,作用是保证在JVM中,该对象仅仅有一个实例存在. 长处:1.降低某些创建比較频繁的或者比較大型的对象的系统开销. 2.省去了new操作符,减少系统内存使 ...

  2. Java设计模式探讨之单例模式

    单例模式是在平时的项目开发中比较常见的一种设计模式,使用比较普遍,网上的资料也是一抓一大把,小Alan也来凑凑热闹,为以后充实点设计模式相关的内容做个简单的开篇. 单例模式是一种创建对象的模式,用于产 ...

  3. 设计模式之单例模式(C#)

    本文来自于本人个人微信公众号,欢迎关注本人微信公众号,二维码附在文章末尾~~~ 一直都特别羡慕能写文章的人,但是由于本人比较懒再加上写文章功底实在是just so so,所以就一搁再搁,最近突然觉得自 ...

  4. 【编程拾遗】C++的static成员函数与单例模式

    static小结 static的引入 static 是C++中非经常常使用的修饰符,它被用来控制变量的存储方式和可见性. 函数内部定义的变量,在程序运行到它的定义处时,编译器为它在栈上分配空间,函数在 ...

  5. C++ 单例模式总结与剖析

    目录 C++ 单例模式总结与剖析 一.什么是单例 二.C++单例的实现 2.1 基础要点 2.2 C++ 实现单例的几种方式 2.3 单例的模板 三.何时应该使用或者不使用单例 反对单例的理由 参考文 ...

  6. Java项目(5)——单例模式的应用与研究

    单例模式是非常别致的一个模式,非常少有人拿它跟其它模式相比,由于,单例模式非常easy,非常特别,作用就是保证一个类有唯一一个实例,并让一个全局变量使得它能被訪问.而保证这个类仅仅被实例化一次的办法就 ...

  7. Android 设计模式之单例模式

    设计模式是前人在开发过程中总结的一些经验,我们在开发过程中依据实际的情况,套用合适的设计模式,能够使程序结构更加简单.利于程序的扩展和维护.但也不是没有使用设计模式的程序就不好.如简单的程序就不用了, ...

  8. 关于Javakeywordsynchronized——单例模式的思考

    精彩的设计模式盛宴刚刚落下帷幕.三天的时间.真是学习到了非常多.当中,遗留的非常多的问题.今天就谈谈synchronized这个keyword.关于对synchronizedkeyword的思考是从单 ...

  9. C++实现线程安全的单例模式

    在某些应用环境下面,一个类只允许有一个实例,这就是著名的单例模式.单例模式分为懒汉模式,跟饿汉模式两种. 首先给出饿汉模式的实现 template <class T> class sing ...

随机推荐

  1. Laravel 安装

    其实,laravel的安装网上给了很多方法,但是你可以直接根据laravel中国官网http://www.golaravel.com/docs/4.1/installation/给出的三种方法,选择其 ...

  2. linux命令学习6-dpkg命令

    dpkg命令是Debian Linux系统用来安装.创建和管理软件包的实用工具. 1. 语法 dpkg (选项) (参数)2. 选项 -i:安装软件包: -r:删除软件包: -P:删除软件包的同时删除 ...

  3. 手动调用NDK编译HelloWorld

    首先,你得有NDK(木有的自行搜索) /home/xxxx/tools/android-ndk-r12b 准备好你的HelloWorld程序源码: #include<stdio.h> in ...

  4. jquey插件开发

    1.概述 jquery插件开发的主要方法有三种: 1.通过$.extend()来扩展jQuery,即在jQuery命名空间下扩展属性,直接在$对象下调用,不需要再dom下调用,也无法在dom元素下调用 ...

  5. Less-css预处理编译

    node编译 第一步:https://nodejs.org/en/  到node官网下载最新的node 第二步:和普通软件一样把node安装好 第三步:运行-cmd,准备安装less 全局安装(整个电 ...

  6. UVa 10667 - Largest Block

    题目大意:这个也是和UVa 836 - Largest Submatrix差不多,修改一下数据就可以套用代码的. #include <cstdio> #include <cstrin ...

  7. bzoj3571————2016——3——12(最小乘积匹配)

    bzoj3571 传送门http://www.lydsy.com/JudgeOnline/problem.php?id=3571 题解: ——————来自伟大的thy大神  http://blog.c ...

  8. var d = document.getElementById 错误

    var d = document.getElementById; var s = d("demo").innerHTML; alert(s); // IE 没有问题,其他浏览器必须 ...

  9. robotium从入门到放弃 四 Robotium常用API

      获取控件 getText() getEditText() getButton() getImage() getImageButton() getEditText() getView() getWe ...

  10. 在centos 6.5 x64中安装 spark-1.5.1

    以下内容参考:http://blog.csdn.net/lovehuangjiaju/article/details/48494737 1.解压安装文件,设置环境变量 这里我们使用的安装文件是已经编译 ...