题目:设计一个类,我们只能生成该类的一个实例

java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。

  单例模式有以下特点:

  1、单例类只能有一个实例。

  2、单例类必须自己创建自己的唯一实例。

  3、单例类必须给所有其他对象提供这一实例。

单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。

a、懒汉式单例

//懒汉式单例类.在第一次调用的时候实例化自己   

package com.yyq;
/**
* Created by Administrator on 2015/9/4.
*/
public class Singleton {
private Singleton(){} //私有的默认构造方法,因此无法使用构造方法实例化
private static Singleton single = null; //注意,这里没有final
public static Singleton getInstance(){ //静态工厂方法
if(single == null)
single = new Singleton();
return single;
}
}

Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。

(事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。)

但是以上懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton实例,下面介绍的饿汉式单例是线程安全的。

b、饿汉式单例

//饿汉式单例类.在类初始化时,已经自行实例化  

 package com.yyq;
/**
* Created by Administrator on 2015/9/4.
*/
public class Singleton {
private Singleton(){} //私有的默认构造方法,因此无法使用构造方法实例化
private static final Singleton SINGLE= new Singleton(); //注意,这里有final
public static Singleton getInstance(){ //静态工厂方法
return SINGLE;
}
}

饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的。

C、登记式单例

//类似Spring里面的方法,将类名注册,下次从里面直接获取。

import java.util.HashMap;
import java.util.Map; /**
* Created by Administrator on 2015/9/4.
*/
public class Singleton {
private static Map<String,Singleton> map = new HashMap<String,Singleton>();
static {
Singleton single = new Singleton();
map.put(single.getClass().getName(),single);
}
//保护的默认构造方法
protected Singleton(){}
public static Singleton getInstance(String name){
if(name == null || name == ""){
name = Singleton.class.getName();
System.out.println("name == null" +"-->name"+name);
}
if(map.get(name) == null){
try{
map.put(name,(Singleton) Class.forName(name).newInstance());
}catch (InstantiationException e){
e.printStackTrace();
}catch (IllegalAccessException e){
e.printStackTrace();
}catch (ClassNotFoundException e){
e.printStackTrace();
}
}
return map.get(name);
}
public String about(){
return "Hello, I am RegSingleton";
}
public static void main(String[] args) {
Singleton single = Singleton.getInstance(null);
System.out.println(single.about());
}
}

登记式单例实际上维护了一组单例类的实例,将这些实例存放在一个Map(登记薄)中,对于已经登记过的实例,则从Map直接返回,对于没有登记的,则先登记,然后返回。

饿汉式和懒汉式区别

这两种乍看上去非常相似,其实是有区别的,主要两点

1、线程安全:

饿汉式是线程安全的,可以直接用于多线程而不会出现问题,懒汉式就不行,它是线程不安全的,如果用于多线程可能会被实例化多次,失去单例的作用。

如果要把懒汉式用于多线程,有两种方式保证安全性,一种是在getInstance方法上加同步,另一种是在使用该单例方法前后加双锁。

2、资源加载:

饿汉式在类创建的同时就实例化一个静态对象出来,不管之后会不会使用这个单例,会占据一定的内存,相应的在调用时速度也会更快,

而懒汉式顾名思义,会延迟加载,在第一次使用该单例的时候才会实例化对象出来,第一次掉用时要初始化,如果要做的工作比较多,性能上会有些延迟,之后就和饿汉式一样了。

什么是线程安全?

如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。

或者说:一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题,那就是线程安全的。

应用

以下是一个单例类使用的例子,以懒汉式为例:

package com.yyq;

/**
* Created by Administrator on 2015/9/4.
*/
public class Singleton {
String name = null;
private Singleton(){}
private static Singleton instance = null;
public static Singleton getInstance(){
if(instance == null)
instance = new Singleton();
return instance;
}
public String getName(){
return this.name;
}
public void setName(String name){
this.name = name;
}
public void printInfo(){
System.out.println("The name is "+this.name);
} public static void main(String[] args) {
Singleton ts1 = Singleton.getInstance();
ts1.setName("Demo01");
Singleton ts2 = Singleton.getInstance();
ts2.setName("Demo02");
ts1.printInfo();
ts2.printInfo();
if(ts1 == ts2)
System.out.println("创建的是同一个实例");
else
System.out.println("创建的不是同一个实例");
}
}

输出结果:

The name is Demo02

The name is Demo02

创建的是同一个实例

P31、面试题2:实现Singleton模式的更多相关文章

  1. 【剑指offer】面试题 2. 实现 Singleton 模式

    面试题 2. 实现 Singleton 模式 题目:设计一个类,我们只能生成该类的一个实例. 单例模式:确保一个类只有一个实例,并提供了一个全局访问点. Java 实现 1.饿汉模式 //饿汉模式 p ...

  2. 剑指offer笔记面试题2----实现Singleton模式

    题目:设计一个类,我们只能生成该类的一个实例. 解法一:单线程解法 //缺点:多线程情况下,每个线程可能创建出不同的的Singleton实例 #include <iostream> usi ...

  3. 剑指offer-面试题2.实例Singleton模式

    题目:设计一个类,我们只能生成该类的一个实例 这道题显然是对设计模式的考察,很明显是单例模式.什么是单例模式呢,就是就像题目所说的只能生成一 个类的实例.那么我们不难考虑到下面几点: 1.不能new多 ...

  4. 剑指Offer面试题:1.实现Singleton模式

    说来惭愧,自己在毕业之前就该好好看看<剑指Offer>这本书的,但是各种原因就是没看,也因此错过了很多机会,后悔莫及.但是后悔是没用的,现在趁还有余力,把这本书好好看一遍,并通过C#通通实 ...

  5. 剑指offer之面试题2:实现Singleton模式

    来源:剑指offer 这篇主要记录<剑指offer>书籍中的面试题2:实现Singleton模式 使用语言:C# 代码环境:VS2017 总共有5中解法,从前往后依次优化. 结构如下: 前 ...

  6. 《剑指offer》面试题2:实现Singleton 模式

    面试题2:实现Singleton 模式 题目:设计一个类,我们只能生成该类的一个实例.   只能生成一个实例的类是实现了Singleton (单例)模式的类型.由于设计模式在面向对象程序设计中起着举足 ...

  7. 剑指Offer对答如流系列 - 实现Singleton模式

    目录 面试题2:实现Singleton模式 一.懒汉式写法 二.饿汉式写法 三.枚举 面试题2:实现Singleton模式 题目:设计一个类,我们只能生成该类的一个实例. 由于设计模式在面向对象程序设 ...

  8. Qt 中使用Singleton模式需小心

    在qt中,使用Singleton模式时一定要小心.因为Singleton模式中使用的是静态对象,静态对象是直到程序结束才被释放的,然而,一旦把该静态对象纳入了Qt的父子对象体系,就会导致不明确的行为. ...

  9. C++ Singleton模式

    地址:http://www.cppblog.com/dyj057/archive/2005/09/20/346.html Singleton模式是常用的设计模式之一,但是要实现一个真正实用的设计模式却 ...

  10. Singleton模式——对象创建型模式

    Singleton模式即为单例模式/单件模式. (一)意图--保证一个类仅有一个实例,并提供一个访问它的全局访问点. 如一台计算机可以有多个端口,但是应该统一管理这些端口,避免访问冲突.--选择Sin ...

随机推荐

  1. Python标准库之urllib,urllib2自定义Opener

    urllib2.urlopen()函数不支持验证.cookie或者其它HTTP高级功能.要支持这些功能,必须使用build_opener()函数创建自定义Opener对象. 1. build_open ...

  2. C# 获得手机归属地功能

    今天通过查资料了解到web的页面抓取功能,应用HttpWebRequest和HttpWebResponse功能,从http://www.showji.com网站中抓取归属地信息 应该说这个方法是从别的 ...

  3. VirtualBox中虚拟Ubuntu添加新的虚拟硬盘

    VirtualBox中装好Ubuntu后,发现硬盘空间不够使用 了.以下是搜集整理的解决办法: 1. 添加新硬盘 设置 -> Storage -> SATA控制器->右击,选择&qu ...

  4. DOM文档对象总结

    DOM总结: DOM:文档对象模型document object model DOM三层模型: DOM1:将HTML文档封装成对象 DOM2:将XML文档封装成对象 DOM3:将XML文档封装成对象 ...

  5. 仿微博视频边下边播之滑动TableView自动播放-b

    Tips:这次的内容分为两篇文章讲述01.[iOS]仿微博视频边下边播之封装播放器 讲述如何封装一个实现了边下边播并且缓存的视频播放器.02.[iOS]仿微博视频边下边播之滑动TableView自动播 ...

  6. kali linux安装vm

    https://download3.vmware.com/software/wkst/file/VMware-Workstation-Full-10.0.2-1744117.i386.bundle v ...

  7. 【BZOJ】【1565】【NOI2009】PVZ 植物大战僵尸

    网络流/最大权闭合子图+拓扑排序 感动死了>_<,一年多以前刚知道网络流的时候听说了这道名字很带感的题目,现在终于有实力切掉它了. 这题是最大权闭合子图模型的经典应用<_<,首 ...

  8. Codeforces Round #241 (Div. 2)->A. Guess a number!

    A. Guess a number! time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  9. 解决myeclipse每次启动注册码过期输入注册码

    每次都需要重新输入一个新的注册码,搞的很不愉快,后来发现原来是因为在[我的文档]下面有一个myeclipse的配置文件,叫.myeclipse.properties 你可以全盘搜索一下这个文件,然后改 ...

  10. float2int

    flaot转int时,会直接舍弃小数为,但是当把f所在的地址的数据当成int解析时,就是另外的情况了. #include<iostream> using namespace std; in ...