博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
单例模式【java版】
阅读量:6574 次
发布时间:2019-06-24

本文共 4076 字,大约阅读时间需要 13 分钟。

一、基本特点

      如何防止创建多个实例:构造方法设置为私有,使得外部无法直接new出实例

      基本组成:a)一个静态的和自身类型相同的成员对象

                      b)私有的构造方法

                      c)获取实例的公有方法,供外部调用,以返回实例

       

二、懒汉式

特点:类被加载时不创建实例,getInstance方法第一次被调用时才创建实例

类代码:

public class LazySingleton {
/** * 静态的和自身类型相同的成员对象 */ private static LazySingleton theLazySingleton=null; /** * 构造方法设置为私有,保证无法从外部new出实例 * LazySingleton myLazySingleton=new LazySingleton();这样的语句就无法通过编译 */ private LazySingleton(){} /** * 供外部调用的获取实例的方法,会在第一次调用时初始化实例 */ public static LazySingleton getInstance(){
if(theLazySingleton==null){
System.out.println("懒汉式单例,第一次调用,先创建,再返回实例!"); theLazySingleton=new LazySingleton(); }else{
System.out.println("懒汉式单例,已不是第一次调用,直接返回实例!"); } return theLazySingleton; } }

主函数:

public static void main(String[] args) {
// TODO Auto-generated method stub System.out.println("开始测试单例模式!"); //尽管使用了两个引用名,实际上指向的是内存中同一个实例 LazySingleton myLazySingleton_A, myLazySingleton_B; myLazySingleton_A=LazySingleton.getInstance(); myLazySingleton_B=LazySingleton.getInstance(); }

运行结果:

三、饿汉式

特点:类被加载时就创建实例

类代码:

public class HungrySingleton {
private static final HungrySingleton theHungrySingleton=new HungrySingleton(); private HungrySingleton(){} public static HungrySingleton getInstance(){
System.out.println("饿汉式单例,实例已在类加载时被创建,故可直接返回实例!"); return theHungrySingleton; } }

主函数:

public static void main(String[] args) {
// TODO Auto-generated method stub System.out.println("开始测试单例模式!"); HungrySingleton myHungrySingleton=HungrySingleton.getInstance(); }

运行结果:

四、多线程环境下的单例模式

    A)线程安全的单例:

  1、效率较高线程安全单例(常用方式)

            “静态内部类”只在getInstance()方法第一次调用的时候才会被加载(实现了lazy),而且其加载过程是线程安全的(实现线程安全)

    基本理论依据:java的class-loading是线程安全的

     详细参考:

//静态内部类实现懒汉式  public class Singleton {            private static class SingletonHolder{          //单例变量            private static Singleton instance = new Singleton();      }            //私有化的构造方法,保证外部的类不能通过构造器来实例化。      private Singleton() {                }            //获取单例对象实例      public static Singleton getInstance() {          System.out.println("我是内部类单例!");          return SingletonHolder.instance;      }  }

  2、效率较低线程安全单例

            a)懒汉式,静态方法getInstance前加“类锁”
                缺点:每次获取实例时都会对类进行加锁操作,影响性能

         实际只需第一次instance==null时加类锁,防止内存中创建了两个实例。

public class Singleton {            //单例实例变量      private static Singleton instance = null;            //私有化的构造方法,保证外部的类不能通过构造器来实例化      private Singleton() {}            //获取单例对象实例      public static synchronized  Singleton getInstance() {                    if (instance == null) {               instance = new Singleton();           }                    System.out.println("我是同步法懒汉式单例!");          return instance;      }  }

            b)饿汉式

                 缺点: 一些未必需要加载的模块会每次都被加载,影响整个系统初次加载速度

public class Singleton {            //单例变量 ,static的,在类加载时进行初始化一次,保证线程安全       private static Singleton instance = new Singleton();                //私有化的构造方法,保证外部的类不能通过构造器来实例化。           private Singleton() {}            //获取单例对象实例           public static Singleton getInstance() {          System.out.println("我是饿汉式单例!");          return instance;      }  }

   B) java“写无序”导致的“非线程安全单例”:双重锁定懒汉式

//双重锁定懒汉式  public class Singleton {            //单例实例变量      private static Singleton instance = null;            //私有化的构造方法,保证外部的类不能通过构造器来实例化      private Singleton() {}            //获取单例对象实例      public static Singleton getInstance() {          if (instance == null) {               synchronized (Singleton.class) {                  if (instance == null) {                       instance = new Singleton();                   }              }          }          System.out.println("我是双重锁定懒汉式单例!");          return instance;      }  }

  java内存模型中的“无序写”(out-of-order writes)机制,

  可能导致:intance<>null时,只是intance=mem,而mem=allocate()还没有完成。

  所谓的“无序写”就是,单条语句instance=new Singleton()

  实际执行时为两条语句:1、mem=new Singleton()

             2、instance=mem

  而这两个操作是无序的

  PS:整条语句执行完,肯定instance中的值是正确的,但两步中间可能有其他线程进来访问instance。

  参考:

     

转载于:https://www.cnblogs.com/edisonfeng/archive/2011/10/22/2221305.html

你可能感兴趣的文章
lnmp安装
查看>>
FTP工作方式
查看>>
Linux文件和目录管理常用命令(中)
查看>>
Configure HUE to store data in MySQL
查看>>
我的友情链接
查看>>
Server2008 中AD的部署
查看>>
RabbitMQ 流控制学习
查看>>
Ubuntu16.04 ssh安及root登录
查看>>
一个工程两个target
查看>>
C语言dos程序源代码分享(进制转换器)
查看>>
php项目中常用的log日志记录方法
查看>>
LogParser 导入MSSQL
查看>>
左侧固定导航栏
查看>>
linux安装go环境并编写第一个go程序
查看>>
解决:laravel出现Please provide a valid cache path.
查看>>
兼容IE浏览器样式的html上传文件控件
查看>>
直接插入排序
查看>>
SQLServer的Top功能
查看>>
CentOS之crontab
查看>>
【在线研讨-现场文字】《敏捷开发用户故事分类与组织结构(二期-3)》2012-07-03...
查看>>