早上看了一篇写单例模式的文章,总结的比较全,可惜仍然没有对单例模式在不同classloader甚至是多个jvm上的分析,在网上搜了一下,找到一个例子并改写如下:
定义一个空接口:
// Null interface, do nothing but you'll see the usage later
public interface IAntiSingleton {
}
定义一个通用的单例模式
public class AntiSingleton implements IAntiSingleton {
private static final AntiSingleton instance = new AntiSingleton();
public static AntiSingleton getInstance() {
return instance;
}
}
继承一个classloader并生成AntiSingleton对象
public class NewClassLoader extends ClassLoader {
public IAntiSingleton createNewOne() throws Exception {
InputStream is = getClass().getResourceAsStream("AntiSingleton.class");
byte[] b = new byte[is.available()];
is.read(b);
Class clz = defineClass(null, b, 0, b.length);
Object o = clz.newInstance();
return (IAntiSingleton) o;
}
}
测试方法:
public class TestAntiSingleton {
public static void main(String[] args) throws Exception {
AntiSingleton instance = AntiSingleton.getInstance();
NewClassLoader loader = new NewClassLoader();
IAntiSingleton newObj = loader.createNewOne();
System.out.println(AntiSingleton.getInstance() == newObj);
}
}
output:
=========
false
总结:
java中,一个类可以有多个定义,并且这些类名可以相同(但同一个类加载器产生类的类名不能相同)。如果不同类加载器两个类名相同,即使类的定义相同,甚至一个类的定义是由另一个类产生的,这两个类也是不同的类。
这也就是输出结果产生false的原因,因为此时两个类虽然名字相同,但是其实已经不是一个类。此时的单例模式,看起来是失效的。注意上面为什么要用接口,因为此时在程序中直接使用NewClassLoader用AntiSingleton对输出结果进行转型,在运行时就会抛出一个类型转换Exception。
可以想到的一种情况是,tomcat中,可以部署很多项目,各个项目中是可以出现相同的类名的,这就需要不同的classloader分别load生成这些类。
此外,GoF计划对“设计模式”进行修订,其中提到了要剔除“单例模式”,很期待修订版早点出来。
分享到:
相关推荐
首先,我们来看一下传统的单例模式实现方式,如懒汉式和饿汉式,但这些方法在多线程环境下可能会存在问题。而使用枚举实现单例模式则能确保线程安全,且避免了序列化问题,是Java推荐的一种实现方式。 ```java ...
单例模式是一种常见的软件设计模式,它保证一个类只有一个实例,并提供全局访问点。在Java中,单例模式通常通过静态方法实现,如`getInstance()`,这样可以确保在整个应用程序生命周期中,类只会创建一个对象。然而...
- 在JVM中,单例模式被广泛应用于加载类的ClassLoader。 - Spring框架大量使用了工厂模式、单例模式、代理模式和装饰器模式。 - Java集合框架中,如ArrayList和LinkedList实现了迭代器模式,HashMap实现了策略...
"双重检查锁定"是一种设计模式,用于确保类的单例属性,同时避免不必要的同步开销。在类加载过程中,这个模式能确保类只被加载一次。 5. 类的全限定名与类加载: 类的全限定名是类的完全标识,包括包名和类名,...
- 单例模式不能扩展为多例模式,且不应由其他类创建实例。 - 单例模式在只有一个实例需要时使用,全程变量可以通过单例模式实现。 6. **设计模式**: - Java I/O库中的装饰者模式用于动态组合功能。 - Session...
A选项错误,单例模式设计初衷即为单例,不易扩展为多例。B选项错误,单例实例由模式自身管理。D选项错误,全局变量本身即为全局可见,无需单例模式。 6. **设计模式**:A选项正确,Java I/O库中的装饰器模式常用于...
- **懒汉式单例模式**:第一次使用时才初始化,提高了加载速度,但线程安全性需额外考虑。 #### 代理模式 代理模式为其他对象提供一种代理以控制对这个对象的访问。 ### Socket Socket是用于在网络中进行通信的...
通过单例模式获取到对象后。就是只有一个对象的类 方法全部都是非static修饰的,调用方式:对象名.方法名(...); 4. 工具类命名: XxxUtil、XxxUtils、XxxTool、XxxTools 3. jar 包 (掌握)...
作者通过单例模式等实例,详细演示了`volatile`在实际编程中的应用方法,以及如何在Java内存模型下理解和利用这一特性。 最后,第四部分则转向多线程的设计架构模式。在这个部分,作者提供了多种设计模式来解决实际...
4. **简化并发控制**:在多线程环境下,Singleton 可以简化对实例化过程的同步控制,确保在并发环境中正确地创建单例。 然而,Singleton 模式也存在一些问题和争议: 1. **反模式**:在某些设计原则(如面向对象的...
单例模式是一种设计模式,确保一个类只有一个实例,并提供一个全局访问点。常见的实现方式有饿汉式(静态常量)、懒汉式(线程不安全的、线程安全的synchronized和双重检查锁定)以及枚举单例。 4. **重写equals...
- **单例模式**:介绍单例模式的实现方式,如饿汉式、懒汉式、双重检查锁定等。 - **工厂模式**:讲解简单工厂、工厂方法和抽象工厂模式的区别和应用场景。 7. **IO流** - **字符流与字节流**:区分两者的处理...
在单例模式中,通常使用私有构造器防止多次实例化。如果子类继承了单例类,必须注意不要破坏单例的性质。通常通过抽象工厂或枚举来解决这个问题。 总结,Java中继承关系的加载顺序遵循“先父后子”的原则,从加载...
2. **单例模式**:为了安全地创建单例,推荐使用双重检查锁定(Double-Check Locking)或枚举单例模式。双重检查锁定利用`volatile`关键字确保线程安全,避免多线程环境中的多次实例化;枚举单例是Java中最安全且...
15. **单例模式与多例的区别**: - **单例模式**确保一个类只有一个实例,并提供一个全局访问点。 - **多例模式**允许类有多个实例,并通过工厂模式控制实例的创建。 16. **工厂模式及其分类**: - **工厂模式**...
对于那些全局唯一且需要频繁使用的公共资源,如数据库连接池,通常采用单例模式。这样可以确保系统中只有一个实例,节省资源并防止并发问题。 6. **依赖注入**: 使用Spring等框架实现依赖注入,可以将公共资源的...
- 单例模式、工厂模式、装饰器模式、代理模式等23种设计模式的解释和应用实例。 10. **Spring框架** - Spring的核心模块:Core、DI、AOP、MVC。 - 注解驱动开发:@Autowired、@Component、@Service、@Repository...
设计模式是软件设计中经过验证的最佳实践,Java中常用的几种设计模式包括工厂模式、单例模式和代理模式等。 - **工厂模式**: - **简单工厂模式**:由一个工厂对象决定创建出哪一种产品类的实例。 - **工厂方法...
1. **单例模式**:单例模式确保某个类只有一个实例,并提供一个全局访问点。 - **特点**:确保在程序运行期间只存在一个实例。 - **应用场景**:适用于配置管理、日志记录、线程池等场景。 2. **Java I/O库**:...
单例模式、工厂模式、代理模式和适配模式是Java中常用的几种设计模式,它们各有不同的应用场景和优势。理解这些设计模式的原理和实现,能够帮助开发者写出更加模块化和可维护的代码。 最后,理解面向对象编程的设计...