设计模式是一种思想,适合于任何一门面向对象的语言。共有23种设计模式。

单例设计模式所解决的问题就是:保证类的对象在内存中唯一。

举例:

A、B类都想要操作配置文件信息Config.java,所以在方法中都使用了Config con=new Config();但是这是两个不同的对象。对两者的操作互不影响,不符合条件。

解决思路:

1.不允许其他程序使用new创建该类对象。(别人new不可控)
2.在该类中创建一个本类实例。
3.对外提供一个方法让其他程序可以获取该对象。

解决方法:单例模式。

步骤:
1.私有化该类的构造函数
2.通过new在本类中创建一个本类对象。
3.定义一个共有的方法将创建的对象返回。

一、饿汉式

雏形:

 class Single
{
private static final Single s=new Single();
private Single(){}
public static Single getInstance()
{
return s;
}
}

为什么方法是静态的:不能new对象却想调用类中方法,方法必然是静态的,静态方法只能调用静态成员,所以对象也是静态的。

为什么对象的访问修饰符是private,不能是public 吗?不能,如果访问修饰符是Public,则Single.s也可以得到该类对象,这样就造成了不可控。

举例:

 public class Single
{
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private static final Single s=new Single();
private Single(){}
public static Single getInstance()
{
return s;
}
}
 public class Main {
public static void main(String args[])
{
Single s=Single.getInstance();
s.setName("张三");
System.out.println(s.getName());
}
}

最后结果为:张三

 二、懒汉式

前面的是饿汉式单例模式,下面开始讲解懒汉式单例模式。

 class Single
{
private static Single s=null;
private Single(){}
public static Single getInstance()
{
if(s==null)
s=new Single();
return s;
}
}

我们可以看到懒汉式和饿汉式相比的区别就是懒汉式创建了延迟对象同时饿汉式的实例对象是被修饰为final类型。

懒汉式的好处是显而易见的,它尽最大可能节省了内存空间。

但是懒汉式又有着弊端,在多线程编程中,使用懒汉式可能会造成类的对象在内存中不唯一,虽然通过修改代码可以改正这些问题,但是效率却又降低了。而且如果想要使用该类对象,就必须创建对象,所以虽然貌似使用懒汉式有好处,但是在实际开发中使用的并不多。

总结:

懒汉式在面试的时候经常会被提到,因为知识点比较多,而且还可以和多线程结合起来综合考量。

饿汉式在实际开发中使用的比较多。

三、懒汉式在多线程中的安全隐患以及解决方案、优化策略。

下面分析懒汉式在多线程中的应用和出现的问题以及解决方法。

懒汉式在多线程中出现的问题:

懒汉式由于多加了一次判断

if(s==null)

导致了线程安全性隐患。因为CPU很有可能在执行完if语句之后切向其它线程。解决线程安全性问题的关键就是加上同步锁。

1.使用同步函数

我们可以直接使用同步函数:

class Single
{
private static Single s=null;
private Single()
{
}
public static synchronized Single getInstance()
{
if(s==null)
s=new Single();
return s;
}
}

但是直接使用同步函数的方法效率十分低下,因为每次调用此方法都需要先判断锁。

2.使用同步代码块

我们也可以使用同步代码块:

 class Single
{
private static Single s=null;
private Single()
{ }
public static Single getInstance()
{
synchronized(Single.class)
{
if(s==null)
s=new Single();
return s;
}
}
}

但是每次调用getInstance方法仍然会判断锁,事实上没有改变效率问题。

3.最终解决方案

我们可以使用另外一种方式,达到只判断一次锁,并且实现同步的目的:

 class Single
{
private static Single s=null;
private Single()
{ }
public static Single getInstance()
{
if(s==null)//和上面的相比只是多增加了一次判断
{
synchronized(Single.class)
{
if(s==null)
s=new Single();
return s;
}
}
return s;
}
}

观察代码可以发现和上面的代码相比,只是增加了一次判断而已,但是,这一次判断却解决了效率问题。

我们可以分析一下这个代码:

4.最终解决方案代码分析和总结

假设我们现在并没有创建单例对象,即s==null,那么我们调用getInstance方法的时候,会进入if块,然后进入同步代码块,此时,别的线程如果想要创建Single实例,就必须获取锁;等当前线程创建完实例对象,释放锁之后,假设正巧有几个线程已经进入了if块中,它们会拿到锁,进入同步代码块,但是由于进行了判空操作,所以不会创建Single实例,而是直接返回已经创建好的Single实例。如果有多个其他线程进入了if块,当它们依次进入同步代码块的时候,同理也不会创建新的Single实例。而没有进入if块的线程,判空操作之后不满足条件,进不了if块,而直接执行了下一条语句return s;其后的线程调用getInstance方法时,只会判断一次s==null,不满足条件直接返回Single单例s,这样就大大提高了了执行效率。

总结:在代码

 if(s==null)
{
synchronized(Single.class)
{
if(s==null)
s=new Single();
return s;
}
}
return s;
中,第一行代码是第一次判空操作,目的是提高效率;第三行代码是同步代码块的入口,目的是保证线程安全;第五行代码进行第二次判空操作是为了保证单例对象的唯一性

【JAVA单例模式详解】的更多相关文章

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

    单例模式的特点 一个类只允许产生一个实例化对象. 单例类构造方法私有化,不允许外部创建对象. 单例类向外提供静态方法,调用方法返回内部创建的实例化对象.  懒汉式(线程不安全) 其主要表现在单例类在外 ...

  2. Java 单例模式详解

    概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. ...

  3. Java 单例模式详解(转)

    概念: java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例.饿汉式单例.登记式单例三种. 单例模式有一下特点: 1.单例类只能有一个实例. 2.单例类必须自己自己创建自己的唯一实例. ...

  4. 9种Java单例模式详解

    单例模式的特点 一个类只允许产生一个实例化对象. 单例类构造方法私有化,不允许外部创建对象. 单例类向外提供静态方法,调用方法返回内部创建的实例化对象. 懒汉式(线程不安全) 其主要表现在单例类在外部 ...

  5. java单例模式详解

    饿汉法 饿汉法就是在第一次引用该类的时候就创建对象实例,而不管实际是否需要创建.代码如下: public class Singleton { private static Singleton = ne ...

  6. android java 设计模式详解 Demo

    android java 设计模式详解 最近看了一篇设计模式的文章,深得体会,在此基础我将每种设计模式的案例都写成Demo的形式,方便读者研究学习, 首先先将文章分享给大家: 设计模式(Design ...

  7. Java内部类详解

    Java内部类详解 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能用到的场景不多,用得最多的是在有事件监听的情况下,并且即使用到也很少去总结内部类的用法.今天我们就 ...

  8. 黑马----JAVA迭代器详解

    JAVA迭代器详解 1.Interable.Iterator和ListIterator 1)迭代器生成接口Interable,用于生成一个具体迭代器 public interface Iterable ...

  9. C++调用JAVA方法详解

    C++调用JAVA方法详解          博客分类: 本文主要参考http://tech.ccidnet.com/art/1081/20050413/237901_1.html 上的文章. C++ ...

随机推荐

  1. 高性能图片服务器–ZIMG

    2011年李彦宏在百度联盟峰会上就提到过互联网的读图时代已经到来1,图片服务早已成为一个互联网应用中占比很大的部分,对图片的处理能力也相应地变成企业和开发者的一项基本技能.需要处理海量图片的典型应用有 ...

  2. CCF第四题无向图打印路径

    #include<iostream> #include<vector> #include<algorithm> #include<stack> #def ...

  3. 补上题代码 hdu1520

    #include<iostream> #include<cmath> #include<algorithm> #include<vector> #inc ...

  4. COGS 2387.[HZOI 2016]2387题解

    题目大意: 给定一个有n个元素的数组,有m个操作,分为两种,分别是询问第k个x的下标和把下标为x的数修改为k. 题目设置了强制在线,故无法预先得知所有操作数. 思路: 有三种思路. 第一种:平衡树 b ...

  5. Intellij IDEA使用总结

    查询快捷键CTRL+N   查找类CTRL+SHIFT+N  查找文件CTRL+SHIFT+ALT+N 查 找类中的方法或变量CIRL+B   找变量的来源CTRL+ALT+B  找所有的子类CTRL ...

  6. 11.2---字符串数组排序,删除变位词(CC150)

    这道题主义的就是,要利用数组自带的sort函数. 此外,注意,利用hash来判断是否出现了. public static ArrayList<String> sortStrings(Str ...

  7. MyEclipse 10 集成Maven

    第一步:安装Maven,作者安装目录是:D:\Java\apache-maven-3.2.5 第二步:配置本地仓库 maven将每次应用过的项目.文件.jar都会存储到maven的仓库中(默认仓库位置 ...

  8. leetcode Add and Search Word - Data structure design

    我要在这里装个逼啦 class WordDictionary(object): def __init__(self): """ initialize your data ...

  9. 【leetcode】Unique Binary Search Trees

    Unique Binary Search Trees Given n, how many structurally unique BST's (binary search trees) that st ...

  10. ios 获得设备型号方法

    以前用UIScreen 的大小来判断设备类型,现在有了iphone6 和 iphone6 plus, 这种方法不能用了.因为当程序不提供相应的启动图片时,系统会把程序运行在320*568的size下, ...