单例模式是设计模式中最常见也最简单的一种设计模式,保证了在程序中只有一个实例存在并且能全局的访问到。比如在Android实际APP 开发中用到的 账号信息对象管理, 数据库对象(SQLiteOpenHelper)等都会用到单例模式。下面针对一些例子分析一下我们在开发过程中应用单例模式需要注意的点。

一、作用
单例模式(Singleton):保证一个类仅有一个实例,并提供一个访问它的全局访问点

二、适用场景

1. 应用中某个实例对象需要频繁的被访问。

2. 应用中每次启动只会存在一个实例。如账号系统,数据库系统。

三、常用的使用方式

(1)懒汉式

这是在开发中很容易就能写出来的一种方式,如下

  1. public class Singleton {
  2. /* 持有私有静态实例,防止被引用,此处赋值为null,目的是实现延迟加载 */
  3. private static Singleton instance = null;
  4. /* 私有构造方法,防止被实例化 */
  5. private Singleton() {
  6. }
  7. /* 1:懒汉式,静态工程方法,创建实例 */
  8. public static Singleton getInstance() {
  9. if (instance == null) {
  10. instance = new Singleton();
  11. }
  12. return instance;
  13. }
  14. }

调用:

  1. Singleton.getInstance().method();

优点:延迟加载(需要的时候才去加载)

缺点: 线程不安全,在多线程中很容易出现不同步的情况,如在数据库对象进行的频繁读写操作时。

(2)加同步锁

既然线程不安全,那就加上同步锁,一种加法如下:

  1. /*2.懒汉式变种,解决线程安全问题**/
  2. public static synchronized Singleton getInstance() {
  3. if (instance == null) {
  4. instance = new Singleton();
  5. }
  6. return instance;
  7. }

更一般的写法是这样

  1. /*加上synchronized,但是每次调用实例时都会加载**/
  2. public static Singleton getInstance() {
  3. synchronized (Singleton.class) {
  4. if (instance == null) {
  5. instance = new Singleton();
  6. }
  7. }
  8. return instance;
  9. }

调用:

  1. Singleton.getInstance().method();

优点:解决了线程不安全的问题。

缺点:效率有点低,每次调用实例都要判断同步锁

补充:在Android源码中使用的该单例方法有:InputMethodManager,AccessibilityManager等都是使用这种单例模式

(3)双重检验锁

要优化(2)中因为每次调用实例都要判断同步锁的问题,很多人都使用下面的一种双重判断校验的办法

  1. /*3.双重锁定:只在第一次初始化的时候加上同步锁*/
  2. public static Singleton getInstance() {
  3. if (instance == null) {
  4. synchronized (Singleton.class) {
  5. if (instance == null) {
  6. instance = new Singleton();
  7. }
  8. }
  9. }
  10. return instance;
  11. }

这种方法貌似很完美的解决了上述效率的问题,它或许在并发量不多,安全性不太高的情况能完美运行,但是,这种方法也有不幸的地方。问题就是出现在这句

  1. instance = new Singleton();

在JVM编译的过程中会出现指令重排的优化过程,这就会导致当 instance实际上还没初始化,就可能被分配了内存空间,也就是说会出现 instance !=null 但是又没初始化的情况,这样就会导致返回的 instance 不完整(可以参考:http://www.360doc.com/content/11/0810/12/1542811_139352888.shtml)。

调用:

  1. Singleton.getInstance().method();

优点:在并发量不多,安全性不高的情况下或许能很完美运行单例模式

缺点:不同平台编译过程中可能会存在严重安全隐患。

补充:在android图像开源项目Android-Universal-Image-Loader https://github.com/nostra13/Android-Universal-Image-Loader中使用的是这种方式

(4)内部类的实现

内部类是一种好的实现方式,可以推荐使用一下:

  1. public class SingletonInner {
  2. /**
  3. * 内部类实现单例模式
  4. * 延迟加载,减少内存开销
  5. *
  6. * @author xuzhaohu
  7. *
  8. */
  9. private static class SingletonHolder {
  10. private static SingletonInner instance = new SingletonInner();
  11. }
  12. /**
  13. * 私有的构造函数
  14. */
  15. private SingletonInner() {
  16. }
  17. public static SingletonInner getInstance() {
  18. return SingletonHolder.instance;
  19. }
  20. protected void method() {
  21. System.out.println("SingletonInner");
  22. }
  23. }

调用:

  1. SingletonInner.getInstance().method();

优点:延迟加载,线程安全(java中class加载时互斥的),也减少了内存消耗

(5)枚举的方法

这是网上很多人推荐的一种做法,但是貌似使用的不广泛,大家可以试试,

  1. /**
  2. * @function:单例模式枚举实现
  3. * @author xuzhaohu
  4. *
  5. */
  6. public enum SingletonEnum {
  7. /**
  8. * 1.从Java1.5开始支持;
  9. * 2.无偿提供序列化机制;
  10. * 3.绝对防止多次实例化,即使在面对复杂的序列化或者反射攻击的时候;
  11. */
  12. instance;
  13. private String others;
  14. SingletonEnum() {
  15. }
  16. public void method() {
  17. System.out.println("SingletonEnum");
  18. }
  19. public String getOthers() {
  20. return others;
  21. }
  22. public void setOthers(String others) {
  23. this.others = others;
  24. }
  25. }

调用:

  1. SingletonEnum.instance.method();

优缺点:如代码中注释。

上面主要讲了单例模式5种创建方法,大家可以根据其优缺点进行个人实际项目中的使用。讲的属于抛砖引玉,大家多提意见。

Android开发设计模式之——单例模式关于线程不安全问题处理的更多相关文章

  1. Android开发UI之在子线程中更新UI

    转自第一行代码-Android Android是不允许在子线程中进行UI操作的.在子线程中去执行耗时操作,然后根据任务的执行结果来更新相应的UI控件,需要用到Android提供的异步消息处理机制. 代 ...

  2. android 开发设计模式---单例模式

    要保证单例,需要做以下几步 必须防止外部可以调用构造函数进行实例化,因此构造函数必须私有化. 必须定义一个静态函数获得该单例 单例使用volatile修饰 使用synchronized 进行同步处理, ...

  3. Android开发-API指南-进程与线程

    Processes and Threads 英文原文:http://developer.android.com/guide/components/processes-and-threads.html ...

  4. 一天一个设计模式——(Singleton)单例模式(线程安全性)

    一.模式说明 有时候,我们希望在应用程序中,仅生成某个类的一个实例,这时候需要用到单例模式. 二.模式类图 三.模式中的角色 Singleton角色,该模式中仅有的一个角色,该角色有一个返回唯一实例的 ...

  5. android 开发设计模式---Builder模式

    我们通过一个例子来引出Builder模式.假设有一个Person类,我们通过该Person类来构建一大批人,这个Person类里有很多属性,最常见的比如name,age,weight,height等等 ...

  6. android 开发设计模式---Strategy模式

    假设我们要出去旅游,而去旅游出行的方式有很多,有步行,有坐火车,有坐飞机等等.而如果不使用任何模式,我们的代码可能就是这样子的. 12345678910111213141516171819202122 ...

  7. android 开发设计模式---观察者模式

    情景1 有一种短信服务,比如天气预报服务,一旦你订阅该服务,你只需按月付费,付完费后,每天一旦有天气信息更新,它就会及时向你发送最新的天气信息. 情景2 杂志的订阅,你只需向邮局订阅杂志,缴纳一定的费 ...

  8. Android 开发中三种多线程

    在开发工程中线程可以帮助我们提高运行速度,Android开发中我知道的线程有四个一个是老生长谈的Thread,第二个是asyncTask,第三个:TimetTask,第四个是Looper,四个多线程各 ...

  9. Android开发中常见的设计模式

    对于开发人员来说,设计模式有时候就是一道坎,但是设计模式又非常有用,过了这道坎,它可以让你水平提高一个档次.而在android开发中,必要的了解一些设计模式又是非常有必要的.对于想系统的学习设计模式的 ...

随机推荐

  1. Bone Collector II

    Bone Collector II Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...

  2. setprecision(int n)等格式函数用法 分类: POJ 2015-06-11 10:56 17人阅读 评论(0) 收藏

    **这些用法前最好用 #include <iostream>    //不要用iostream.h ,会出现好多问题 #include <iomanip> // io 流控制头 ...

  3. ural 1113,jeep problem

    题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1113 网上的解答铺天盖地.我硬是花了两天才懂了点. wiki上的解释:https://e ...

  4. Spring声明式事务管理与配置详解

    转载:http://www.cnblogs.com/hellojava/archive/2012/11/21/2780694.html 1.Spring声明式事务配置的五种方式 前段时间对Spring ...

  5. WF3.0 CallExternalMethod使用技巧

    CallExternalMethod用于工作流向宿主进程中通信 简单的介绍一下它的使用技巧,参照网上的一个questioner源码进行了改进,因为我感觉这个源码提供的通信demo过于繁琐. 看看ser ...

  6. ie兼容整理

    那里面有东西要长研究 ie bug集合关于如何给各种浏览器打bug,可查询:browser hacks 几篇处理ie问题的帖子,帖子1

  7. ContentProvider官方教程(6)provider支持的数据类型

    Provider Data Types Content providers can offer many different data types. The User Dictionary Provi ...

  8. Path文件操作实例

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AddProduct.asp ...

  9. BZOJ 2433 智能车比赛(计算几何+最短路)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2433 题意:若干个矩形排成一排(同一个x之上最多有一个矩形),矩形i和i+1相邻.给定两 ...

  10. choco命令

    C:\Users\Administrator>chocoChocolatey v0.10.0 C:\Users\Administrator>choco --version0.10.0 C: ...