单例对象是一种常用的设计模式。在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在。这样的模式有几个好处:
1、某些类创建比较频繁,对于一些大型的对象,这是一笔很大的系统开销。
2、省去了new操作符,降低了系统内存的使用频率,减轻GC压力。
3、有些类如交易所的核心交易引擎,控制着交易流程,如果该类可以创建多个的话,系统完全乱了。所以只有使用单例模式,才能保证核心交易服务器独立控制整个流程。
常见的五种单例模式实现方法:饿汉式,懒汉式,双重检测锁式,静态内部类式,枚举单例。重点是:饿汉式和懒汉式。
一:饿汉单例模式
饿汉式,即单例对象立即加载。
特点:线程安全,调用效率高,但是,不能延迟加载。
问题:如果只是加载本类,而不是要调用getInstance(),甚至永远没有调用,则会造成资源浪费!
饿汉单例模式代码中,static变量会在类加载时初始化,此时也不会涉及多个线程对象访问该对象的问题。虚拟机保证只会加载一次该类,肯定不会发生并发访问的问题。因此,可以省略synchronized关键字,所以效率高。
package com.DesignPattern;
//饿汉式单例模式
public class Singleton01 {
//类初始化时,立即加载该对象。加载类时,是天然的线程安全的。但是如果用不到该实例,造成资源浪费。
private static /*final*/ Singleton01 instance = new Singleton01();
//私有化构造器
private Singleton01(){
}
//方法没有synchronized,调用效率高
public static /*synchronized*/ Singleton01 getInstance(){
return instance;
}
}
二、懒汉式单例模式
懒汉式,单例对象延迟加载。真正用的时候才加载,资源利用率高。
特点:线程安全,调用效率不高,但是,可以延迟加载。
问题:每次调用getInstance()方法都要同步(并发效率较低),否则,在多线程中,容易创建不止一个Singleton02实例。
package com.DesignPattern;
//懒汉式单例模式
public class Singleton02 {
private static Singleton02 instance = null;
private Singleton02(){
}
public static synchronized Singleton02 getInstance(){
if(instance==null){
instance = new Singleton02();
}
return instance;
}
}
三、静态内部类式
静态内部类式,外部内没有static属性,不会立即加载对象。
特点:线程安全,调用效率高,可以延迟加载。
只有真正调用getInstance()时,才会加载静态内部类。instance是static final类型,保证了内存中只有这样一个实例存在,而且只能被赋值一次,从而保证了线程安全。兼备了并发高效调用和延迟加载的优势。
package com.DesignPattern;
//静态内部类式单例模式
public class Singleton03 {
private Singleton03(){}
private static class SingletonClassInstance{
private static final Singleton03 instance = new Singleton03();
}
public static Singleton03 getInstance(){
return SingletonClassInstance.instance;
}
}
四、测试程序
package com.DesignPattern;
public class Test {
public static void main(String[] args) {
Singleton01 instance = Singleton01.getInstance();
Singleton01 instance2 = Singleton01.getInstance();
System.out.println(instance);
System.out.println(instance2);
System.out.println(instance==instance2);
}
}
测试结果