关于Java中的单例模式

原创 2013年12月06日 12:48:29

--------------------------- 题记

查了很多资料,然后汇总总结了一篇单例模式的文章。


--------------------------- 查询的相关博客资料

单例模式-内部类:

http://blog.sina.com.cn/s/blog_6d2890600101gb8x.html

http://blog.sina.com.cn/s/blog_765e27790101ab8x.html

http://blog.csdn.net/shutear/article/details/8038847

 

Synchronized

http://zhangjunhd.blog.51cto.com/113473/70300

http://hi.baidu.com/jiangyangw3r/item/a3d53ed6bb72b21e20e2504c

 

单例模式:

http://www.cnblogs.com/coffee/archive/2011/12/05/inside-java-singleton.html

http://blog.sina.com.cn/s/blog_75247c770100yxpb.html

http://blog.csdn.net/wutianyin222/article/details/7911829



--------------------------- 单例模式

有些时候,允许自由创建某个类的实例没有意义,还可能造成系统性能下降(因为创建对象锁带来的系统开销问题)。


使用单例模式的三个条件

 使用private修饰该类的构造方法。

 提供一个public static的公共静态方法作为该类的访问点。

 必须缓存已创建的对象,使用private static私有静态成员变量类缓存。


使用代理模式的两个优势

 减少创建Java实例所带来的系统开销。

 便于系统跟踪单个Java实例的生命周期、实例状态等。


单例一:预加载

优点:线程安全,线程同时访问无性能下降问题。

缺点:加载类就创建对象,如果长期不使用,就导致资源浪费。

package test;

public class Singleton {
	//静态缓存点
	private static Singleton singleton = new Singleton();
	
	//私有构造方法
	private Singleton() {}
	
	//静态访问点
	public static Singleton getInstance() {

		return singleton;
	}
	
}

单例二:延迟加载(同步方法锁

优点:延迟加载,按需分配内存,线程安全(懒汉模式)。

缺点:多线程访问时,性能降低。

package test;

public class Singleton {
	//静态缓存点
	private static Singleton singleton;
	
	//私有构造方法
	private Singleton() {}
	
	//静态访问点
	public synchronized static Singleton getInstance() {//给方法上锁,不同线程不能同时进入该方法
		if (singleton == null) singleton = new Singleton();
		
		return singleton;
	}
	
}

注:对static方法使用synchronized时,加锁的对象为SingletonDemo.class,这个是线程安全的。如果对于成员方法(没有static修饰),加锁的对象为SingletonDemo.this,如果其他线程该类的其他对象访问该方法,synchronized对它是无效的,因为是对象锁,锁的是本对象其他线程对于该方法的访问。


单例三:延迟加载(双重检查锁

优点:延迟加载,按需分配内存,线程安全(懒汉模式)。

缺点:第一次线程同时访问时性能下降。

package test;

public class Singleton {
	//静态缓存点
	private static Singleton singleton;
	
	//私有构造方法
	private Singleton() {}
	
	//静态访问点
	public static Singleton getInstance() {
		if (singleton == null)
			synchronized (Singleton.class) {//给该类上锁,不同线程不能同时进入该类同步块
				if (singleton == null) singleton = new Singleton();
			}
		
		return singleton;
	}
	
}

注:如代码所示,此代码如果有成员变量需要对外访问,那么需要加入volatile关键字修饰对应的对象。若没有该关键字,则获取到的该成员变量不准确,该单例是个不健康的单例模式。若使用该关键字,则性能会降低,少了JVM的代码优化功能(具体看博客分析)。


单例四:延迟加载(内部类

package test;

public class Singleton {
	private static class SingletonHolder {
		//静态缓存点
		private static Singleton singleton = new Singleton();
	}
	
	//私有构造方法
	private Singleton() {}
	
	//静态访问点
	public static Singleton getInstance() {
		
		return SingletonHolder.singleton;
	}

}

注:因为java机制规定,内部类SingletonHolder只有在getInstance方法第一次调用的时候才会被加载(实现了lazy),而且其加载过程是线程安全的(JVM实现线程安全)。内部类加载的时候实例化一次singleton


单例模式举例

 Servlet工作流程图如下:

 

 

那么在整个过程中,首先是容器接受请求,再把所有请求发送给dispatch中转站,中转站解析请求之后,根据请求的信息来调用不同的servlet,在调用servlet的时候使用多线程来代替多进程,从而提高性能。

在这过程中,有两个地方是单例,第一个是Dispatch类是个单例模式,第二个是Servlet容器,是个容器类型的单例。


 Servlet中的单例:

 Dispatch:标准的单例模式。

 Servlet容器:使用Map<String, Object>缓存的单例模式。


单例模式与工厂模式的结合举例

package test;

public class Singleton {
	//静态缓存点
	private static Singleton singleton;
	
	//私有构造方法
	private Singleton() {}
	
	//静态访问点(工厂)
	public static Singleton factory(String className) {
		if (singleton == null)
			synchronized (Singleton.class) {
				try {
					if (singleton == null) 
						singleton = (Singleton) Class.forName(className).newInstance();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		
		return singleton;
	}

}

@ 符号 在java中是什么语法 代表什么

java中@是什么     J2SE 提供的最后一个批注是 @SuppressWarnings。该批注的作用是给编译器一条指令,告诉它对被批注的代码元素内部的某些警告保持静默。     一点背景:...
  • skyboy11yk
  • skyboy11yk
  • 2013年10月12日 16:49
  • 38760

关于java中<T>问题

关于java中问题 Jdk5.0新特性Generic Types (泛型) 原文 来源: 中国IT实验室 作者: 未知 责编: 宝良 1. 介绍 2.定义简单Java泛型 其实Java...
  • zhengqiqiqinqin
  • zhengqiqiqinqin
  • 2013年05月31日 19:22
  • 35827

Java中布尔类型操作&=,|=与^=的使用

今天在对同事的代码进行code review的时候,见到一个比较好玩的写法。“flag &= false;”,乍一看,还感觉他写错了,但是程序可以正常运行,赶紧去百度,看一下这个写法到底是怎么一回事,...
  • ziwen00
  • ziwen00
  • 2014年10月31日 16:35
  • 17994

java中==与equel的区别

值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中。     ==操作比较的是两个变量的值是否相等,对于引用型变量表示的是两个变量...
  • hellokatewj
  • hellokatewj
  • 2014年03月26日 17:43
  • 2840

java this 3种常见用法 详解

this 关键字 1.区分成员变量和局部变量 2.代表当前对象 3.构造器之间调用
  • u012176204
  • u012176204
  • 2017年01月17日 09:41
  • 3097

【数据结构】之二叉树的java实现

二叉树的定义: 二叉树是树形结构的一个重要类型。许多实际问题抽象出来的数据结构往往是二叉树的形式,即使是一般的树也能简单地转换为二叉树,而且二叉树的存储结构及其算法都较为简单,因此二叉树显得特别重要。...
  • wuwenxiang91322
  • wuwenxiang91322
  • 2013年10月02日 09:28
  • 80322

Java可以做什么及可以给我们带来什么?

一般来说,Java是一个功能强大的软件平台。一套完整的Java平台将会给你带来如下特性: 开发工具箱:...
  • stewen_001
  • stewen_001
  • 2014年03月12日 16:06
  • 2904

Java 进度条控件的使用

利用JProcessBar类可以实现一个进度条,它本身不过是一个矩形控件,通过填充它的部分或全部来指示一个任务的执行情况,可以放置到一个新的线程中运行。 示例如下:...
  • kehyuanyu
  • kehyuanyu
  • 2014年05月19日 17:44
  • 8686

最小堆和最大堆的JAVA实现

/** * 文件名:BinaryHeap.java * 时间:2014年11月3日下午7:15:34 * 作者:修维康 */ package chapter6; import java.ut...
  • xiuweikang
  • xiuweikang
  • 2014年11月04日 16:37
  • 4438

java事务处理全解析

最近学习java事务,看到一位前辈的系列博客不错,转载过来作为记录 转载地址:http://www.davenkin.me/post/2013-02-16/40048284001    (一)Ja...
  • huilangeliuxin
  • huilangeliuxin
  • 2015年02月03日 10:26
  • 55411
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于Java中的单例模式
举报原因:
原因补充:

(最多只允许输入30个字)