java 单例模式的实例详解
作者:lqh 发布时间:2023-10-08 05:14:08
java 单例模式的实例详解
概念:
java中单例模式是一种常见的设计模式,单例模式分三种:懒汉式单例、饿汉式单例、登记式单例三种。
单例模式有一下特点:
1、单例类只能有一个实例。
2、单例类必须自己自己创建自己的唯一实例。
3、单例类必须给所有其他对象提供这一实例。
单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。
首先看一个经典的单例实现。
public class Singleton {
private static Singleton uniqueInstance = null;
private Singleton() {
// Exists only to defeat instantiation.
}
public static Singleton getInstance() {
if (uniqueInstance == null) {
uniqueInstance = new Singleton();
}
return uniqueInstance;
}
// Other methods...
}
Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。(事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。)
但是以上实现没有考虑线程安全问题。所谓线程安全是指:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。显然以上实现并不满足线程安全的要求,在并发环境下很可能出现多个Singleton实例。
public class TestStream {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
//该类只能有一个实例
private TestStream(){} //私有无参构造方法
//该类必须自行创建
//有2种方式
/*private static final TestStream ts=new TestStream();*/
private static TestStream ts1=null;
//这个类必须自动向整个系统提供这个实例对象
public static TestStream getTest(){
if(ts1==null){
ts1=new TestStream();
}
return ts1;
}
public void getInfo(){
System.out.println("output message "+name);
}
}
/**
*
*/
public class TestMain {
public static void main(String [] args){
TestStream s=TestStream.getTest();
s.setName("张孝祥");
System.out.println(s.getName());
TestStream s1=TestStream.getTest();
s1.setName("张孝祥");
System.out.println(s1.getName());
s.getInfo();
s1.getInfo();
if(s==s1){
System.out.println("创建的是同一个实例");
}else if(s!=s1){
System.out.println("创建的不是同一个实例");
}else{
System.out.println("application error");
}
}
}
运行结果:
张孝祥
张孝祥
output message 张孝祥
output message 张孝祥
创建的是同一个实例
结论:由结果可以得知单例模式为一个面向对象的应用程序提供了对象惟一的访问点,不管它实现何种功能,整个应用程序都会同享一个实例对象。
1.饿汉式单例类
//饿汉式单例类.在类初始化时,已经自行实例化
public class Singleton1 {
//私有的默认构造子
private Singleton1() {}
//已经自行实例化
private static final Singleton1 single = new Singleton1();
//静态工厂方法
public static Singleton1 getInstance() {
return single;
}
}
2.懒汉式单例类
//懒汉式单例类.在第一次调用的时候实例化
public class Singleton2 {
//私有的默认构造子
private Singleton2() {}
//注意,这里没有final
private static Singleton2 single=null;
//静态工厂方法
public synchronized static Singleton2 getInstance() {
if (single == null) {
single = new Singleton2();
}
return single;
}
}
3.登记式单例类
import java.util.HashMap;
import java.util.Map;
//登记式单例类.
//类似Spring里面的方法,将类名注册,下次从里面直接获取。
public class Singleton3 {
private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();
static{
Singleton3 single = new Singleton3();
map.put(single.getClass().getName(), single);
}
//保护的默认构造子
protected Singleton3(){}
//静态工厂方法,返还此类惟一的实例
public static Singleton3 getInstance(String name) {
if(name == null) {
name = Singleton3.class.getName();
System.out.println("name == null"+"--->name="+name);
}
if(map.get(name) == null) {
try {
map.put(name, (Singleton3) 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) {
Singleton3 single3 = Singleton3.getInstance(null);
System.out.println(single3.about());
}
}
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
来源:http://geek.csdn.net/news/detail/239882
猜你喜欢
- 目录断言对象、数组、集合ObjectUtilsStringUtilsCollectionUtils文件、资源、IO 流FileCopyUti
- 本文介绍C# lock关键字,C#提供了一个关键字lock,它可以把一段代码定义为互斥段(critical section),互斥段在一个时
- 本文实例讲述了JavaMail实现邮件发送的方法。分享给大家供大家参考。具体如下:下载 activation.jar 和 mail.jar配
- 1.狂妄的WPF相对传统的Windows图形编程,需要做很多复杂的工作,引用许多不同的API。例如:WinForm(带控件表单)、GDI+(
- 修改方法有两个1.方法1:点“编辑”-->“列选择模式”2.方法2:快捷键Shift+Alt+Insert修改后结果如下:来源:htt
- 本文通过C#程序代码展示如何给PDF文档添加可视化数字签名和不可见数字签名。可视化数字签名,即在PDF文档中的指定页面位置添加签名,包含相关
- 一般有点开发经验的朋友都能实现这样的功能,只不过是效率上的问题。我们一般在面对这样的问题时,总会平铺直序的联想到,先生成一个数组,然后在一个
- java:使用匿名类直接new接口java中的匿名类有一个倍儿神奇的用法,见下面代码示例:package contract;public i
- 考虑一个场景,轮流打印0-100以内的技术和偶数。通过使用 synchronize 的 wait,notify机制就可以实现,核心思路如下:
- 上一篇JavaMail入门第四篇 接收邮件中,控制台打印出的内容,我们无法阅读,其实,让我们自己来解析一封复杂的邮件是很不容易的,邮件里面格
- 一、序言Java多线程编程线程池被广泛使用,甚至成为了标配。线程池本质是池化技术的应用,和连接池类似,创建连接与关闭连接属于耗时操作,创建线
- 本文实例为大家分享了本地图片或者网络图片高斯模糊效果(毛玻璃效果),具体内容如下首先看效果图1.本地图片高斯模糊2.网络图片高斯模糊gith
- 在阻塞队里中,除了对元素进行增加和删除外,我们可以把元素的删除做一个延迟的处理,即使用DelayQueue的方法。本文就来和大家聊聊Java
- 最近因为用的发送邮件的地方,就查询了资料,总结以下几个方法1、利用新浪邮箱发送2、利用公司邮箱发送3、利用CDO发送,这种方式要引用Inte
- HTTPclient保持长连接首先解释一下什么是长连接当我们向一台服务器发起请求时,我们需要和对方建立一条通道,去传输数据,所谓的短连接,就
- 要说this和super就不得不说Java的封装和继承了,首先说封装,这是一种思想,算不上一种技术,核心思想就是将对象的同一行为和状态看成是
- DataHub 类似于传统大数据解决方案中 Kafka 的角色,提供了一个数据队列功能。DataHub 除了供了一个缓冲的队列作用。同时由于
- Map集合和Collection集合的区别Map集合是有Key和Value的,Collection集合是只有Value。Collection
- 通常,在这个页面中会用到很多控件,控件会用到很多的资源。Android系统本身有很多的资源,包括各种各样的字符串、图片、动画、样式和布局等等
- 功能描述1、创建扑克牌。包括四种花色(黑桃,红心,梅花,方块),十三种点数(2-10,J,Q,K),不考虑大小王。2、创建两个玩家。包括玩家