package com.tag2;
public class 单例模式 {
/**
* 应用场景:
* 1. 系统访问人数
* 2. 系统内部事件
* 3. 系统操作日志
* 4. 系统出错日志
* 5. 系统配置访问接口
* ...
* [单例主要应用于一个类只有一个实例]
* 单例模式发展.
* *. 经典的单例模式
public class Singleton {
private static Singleton instance = null; [懒汉式]
protected Singleton() {
// Exists only to defeat instantiation.
}
public static Singleton getInstance() {
if(instance == null) {
instance = new ClassicSingleton();
}
return instance;
}
}
* 点评:这个类只到getInstance()方法被第一次调用时才被创建,但是一般的程序是应用于多线程环境下,这个类线程不安全
*
public synchronized static Singleton getInstance() {
if(singleton == null) {
singleton = new Singleton();
}
logger.info("created singleton: " + singleton);
return singleton;
}
* 同步方法可以解决线程安全问题,但是同步方法开销会增大,为了整体系统的效率,尽量不要使用同步.
*
public class Singleton {
private static Singleton instance = new Singleton();[饿汉式]
}
public static Singleton getInstance() {
return Singleton.instance;
}
* 点评:Bob Lee的写法,在类加载的时候实例就会被创建,只能通过getInstance()接口访问,能够实现线程同步
*
* Spring如何实现单例:
* ApplicationContext context=FileSystemXmlApplicationContext(String configLocation)
* ApplicationContext context=ClassPathXmlApplicationContext(String configLocation)
* 这两个都是声名配置文件的,但是加入的是同一个域.
* public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
...
}
* Synchronization monitor for the "refresh" and "destroy"
* private final Object startupShutdownMonitor = new Object();
* 在对象中声名一个最终对象进行锁定,这样Application一次就只能有一个方法进入.
* Struts如何实现单例:
public static Class applicationClass(String className,
ClassLoader classLoader)
throws ClassNotFoundException {
if (classLoader == null) {
// Look up the class loader to be used
classLoader = Thread.currentThread().getContextClassLoader();
if (classLoader == null) {
classLoader = RequestUtils.class.getClassLoader();
}
}
// Attempt to load the specified class
return (classLoader.loadClass(className));
}
* 这是Struts得到类加载器并加载一个类.如果类加载器为null则使用当前线程的ClassLoader
* 有人可能会问如果是多线程不是会有问题了吗?我想说的是这是通过类的反映来返回类对象,并不是所有的对象都
* 需要使用多线程支持的,毕竟多线程要处理线程同步,开销太大.
* 现在再来介绍一个Struts如何应用多线程.[Action]
* <p>Return an <code>Action</code> instance that will be used to process
* the current request, creating a new one if necessary.</p>
protected Action processActionCreate(HttpServletRequest request,
HttpServletResponse response, ActionMapping mapping)
throws IOException {
String className = mapping.getType();
Action instance;
synchronized (actions) {
// Return any existing Action instance of this class
instance = (Action) actions.get(className);
if (instance != null) {
if (log.isTraceEnabled()) {
log.trace(" Returning existing Action instance");
}
return (instance);
}
// Create and return a new Action instance
if (log.isTraceEnabled()) {
log.trace(" Creating new Action instance");
}
try {
instance = (Action) RequestUtils.applicationInstance(className);
// Maybe we should propagate this exception
// instead of returning null.
} catch (Exception e) {
log.error(getInternal().getMessage("actionCreate",
mapping.getPath()), e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
getInternal().getMessage("actionCreate", mapping.getPath()));
return (null);
}
actions.put(className, instance);
if (instance.getServlet() == null) {
instance.setServlet(this.servlet);
}
}
return (instance);
}
* 点评:actions是一个HashMap实例,这里使用同步代码块的方法synchronized(actions)[注意:同步代码块比同步方法开销小]
* 当一个请求过来时[线程],这里使用了同步,每一次都从actions中得到对象.如果不为空,则返回,如果为空则通过反映生成对象并返回.
* 这其实也属于单例注册.
* 上面介绍了Spring对应多个配置文件时用的同步,Struts的核心Action的同步,下面介绍一个Spring的核心Bean是如何实现单例的.
*
* Return the (raw) singleton object registered under the given name,
* creating and registering a new one if none registered yet.
public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
Assert.notNull(beanName, "'beanName' must not be null");
synchronized (this.singletonObjects) {
// Re-check singleton cache within synchronized block.
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
if (this.singletonsCurrentlyInDestruction) {
throw new BeanCreationNotAllowedException(beanName,
"Singleton bean creation not allowed while the singletons of this factory are in destruction " +
"(Do not request a bean from a BeanFactory in a destroy method implementation!)");
}
if (logger.isDebugEnabled()) {
logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
}
beforeSingletonCreation(beanName);//singletonsCurrentlyInCreation,同步的集合,添加BeanName
try {
singletonObject = singletonFactory.getObject();//返回这个对象.
}
finally {
afterSingletonCreation(beanName);//singletonsCurrentlyInCreation.同步的集合中,移除BeanName
}
addSingleton(beanName, singletonObject);//添加对象到singletonObjects
}
return (singletonObject != NULL_OBJECT ? singletonObject : null);
}
}
* 细心的读者会发现,Struts和Spring都是采用单例注册器的方式实现的.
* private final Map singletonObjects = CollectionFactory.createConcurrentMapIfPossible(16);
* 这里根据你的jdk版本判断使用哪种同步Map
* if JDKVersion>JAVA_15[或者包括edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap]
* new ConcurrentHashMap(initialCapacity)
* else
* Collections.synchronizedMap(new HashMap(initialCapacity));
* 如果单例注册器中没有此对象
* 1. beforeSingletonCreation(beanName); //监视创建对象前
* 2. singletonObject = singletonFactory.getObject();//返回对象
*singletonFactory.getObject();这是接口方法,这个接口由程序在调用的时候实现.
*getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);//创建方法就是在子类要重写的
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
* 3.afterSingletonCreation(beanName);//监视创建对象后
* 4.addSingleton(beanName, singletonObject);//添加对象到singletonObjects
* 5.返回该对象.
* 综上所述:在应用于系统资源时,为了提供同一接口,需要同步信息,但是Struts和Spring都使用了代码块同步,我们写程序的时候也要向
* 那些大师学习,尽量同步代码块.
*
*/
}
分享到:
相关推荐
李建忠老师的设计模式-单例模式讲解,示例以C++编程语言呈现。
设计模式-单例模式脑图
Java设计模式-单例模式详解 单例模式是 Java 设计模式中的一种常用的设计模式,旨在保证一个类仅有一个实例,并提供一个访问它的全局访问点。单例模式的目的是为了保证在一个进程中,某个类有且仅有一个实例。 ...
ava常用设计模式-单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一,有以下特点: 1. 单例类只能有一个实例。 2. 单例类必须自己创建自己的唯一实例。 3. 单例类必须给所有其他对象提供这一...
本资源“一例读懂设计模式-单例模式、简单工厂模式.zip”旨在帮助初学者通过实例深入理解这两种重要设计模式:单例模式和简单工厂模式。以下是关于这两个模式的详细讲解。 1. **单例模式**: 单例模式是一种限制类...
设计模式-单例模式 单例模式是一种常见的设计模式,它的主要作用是确保在内存中仅创建一次对象,并提供一个全局访问点。单例模式有两种类型:饿汉类型和懒汉类型。 饿汉类型的单例模式是在类加载时创建对象,例如...
单例模式是一种常用的设计模式,它在软件工程中扮演着控制类实例化过程的角色,确保一个类只有一个实例,并提供全局访问点。这种模式在PHP中尤其常见,特别是在需要频繁实例化然后销毁的对象,或者需要控制共享资源...
在Java编程语言中,设计模式是一种经过验证的解决常见软件设计问题的最佳实践。单例模式是其中最常用的一种,它的核心思想是确保一个类只有一个实例,并提供全局访问点。单例模式的应用场景包括:控制资源的访问、...
JAVA-设计模式-创建型模式-单例模式
**设计模式——单例模式** 单例模式是一种广泛应用于软件设计中的创建型设计模式,它的核心思想是确保一个类只有一个实例,并提供一个全局访问点。这样做的好处在于控制共享资源的访问,比如线程安全的数据库连接池...
### 设计模式—单例设计模式详解 #### 定义 单例模式是一种常见的创建型设计模式,其核心思想在于确保一个类仅有一个实例存在,并且该实例由该类自行创建,随后向整个系统提供这一唯一实例。 #### 类图解析 在设计...
android 单例模式 干货 告诉你哪种单例模式最实用 最好用 不再迷茫
在iOS开发中,设计模式是解决常见编程问题的模板,为代码组织提供了标准结构。其中,单例模式是一种被广泛...同时,随着Swift的 Combine 框架和轻量级依赖注入的流行,有些情况下可以考虑使用其他设计模式来替代单例。
### Java设计模式——单例模式详解 #### 一、单例模式概述 单例模式是设计模式中的一个重要组成部分,属于创建型模式之一。其主要作用是确保某个类仅有一个实例存在,并提供一个全局访问该实例的方法。这在很多场景...
**单例模式**是软件设计模式中的一种,属于创建型模式。在C++中,单例模式确保一个类只有一个实例,并提供一个全局访问点。这种模式通常用于管理共享资源,如数据库连接、日志系统或者配置文件等。单例模式的主要...
单例设计模式是一种常用的设计模式,其主要目的是确保一个类只有一个实例,并提供全局访问点。在Java中,实现单例模式通常有多种方式,包括懒汉模式、饿汉模式、静态内部类以及枚举类型。 1. **懒汉模式**: 懒汉...
单例模式是软件设计模式中的一种,它保证一个类只有一个实例,并提供全局访问点。这种模式在许多场景下非常有用,比如控制共享资源、管理系统级别的对象,如数据库连接池或者线程池等。单例模式的核心在于限制类的...
压缩包代码是一个简单的C++单例模式实现。 在这个例子中,Singleton 类有一个私有的构造函数和一个私有的析构函数,这防止了外部代码直接创建或销毁实例。getInstance 方法是一个静态方法,它返回一个指向 Singleton...
单例模式是软件设计模式中的一种经典模式,其主要目的是保证一个类只有一个实例,并提供一个全局访问点。在Java中,有多种实现单例模式的方法,包括简单实现、双重检查锁定(Double-Checked Locking)、静态内部类和...