学而时习之,不亦说乎!
--《论语》
五种单例模式:
单例的作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。
常见单例模式实现:
1.饿汉式单例模式。
2.懒汉式单例模式。
3.双重检测锁单例模式。
4.静态内部类单例模式。
5.枚举单例模式。
1.饿汉式单例模式。
package com.zby.pattern;
import java.io.ObjectStreamException;
import java.io.Serializable;
/**
*
* <class description> 饿汉式单例模式。优点:类只会加载一次,在类加载的时候直接实例化一次,没有线程安全问题。
* 缺点:类加载就实例化,如果只需要加载这个类而不需要实例化对象,这个类又很耗内存,会浪费资源。
*
* @author: zby
* @version: 1.0, 2017年6月22日
*/
public class Singleton01 implements Serializable {
private static final long serialVersionUID = 1L;
// 类加载实例化对象
private static final Singleton01 s = new Singleton01();
// 私有化构造方法
private Singleton01() {
// 避免反射破坏单例
if (null != s) {
throw new RuntimeException("No,you can't do this!");
}
}
// 提供全局访问点
public static Singleton01 getInstance() {
return s;
}
/**
*
* <method description>防止对象反序列化时破坏单例
*
* @return
* @throws ObjectStreamException
*/
private Object readResolve() throws ObjectStreamException {
return s;
}
}
2.懒汉式单例模式。
package com.zby.pattern;
import java.io.ObjectStreamException;
import java.io.Serializable;
/**
*
* <class description> 懒汉式单例模式。优点:只有在真正使用的时候才回去实例化对象,避免浪费资源。
* 缺点:需要将获取实例的方法同步,否则会出现线程安全问题,但是每次获取实例都进行同步 ,降低效率。
*
* @author: zby
* @version: 1.0, 2017年6月22日
*/
public class Singleton02 implements Serializable {
private static final long serialVersionUID = 1L;
// 私有化静态实例
private static Singleton02 s;
// 私有化构造方法
private Singleton02() {
// 避免反射破坏单例
if (null != s) {
throw new RuntimeException("No,you can't do this!");
}
}
// 提供全局访问点,需要进行同步
public static synchronized Singleton02 getInstance() {
if (null == s) {
// 第一次获取实例的时候实例化对象
s = new Singleton02();
}
return s;
}
/**
*
* <method description>防止对象反序列化时破坏单例
*
* @return
* @throws ObjectStreamException
*/
private Object readResolve() throws ObjectStreamException {
return s;
}
}
3.双重检测锁单例模式。
package com.zby.pattern;
import java.io.ObjectStreamException;
import java.io.Serializable;
/**
*
* <class description> 双重检测锁单例模式
* 优点:延迟加载,而且只会在创建时同步。缺点:由于编译器优化和JVM底层内部模型,偶尔会出问题,不建议使用
*
* @author: zby
* @version: 1.0, 2017年6月22日
*/
public class Singleton03 implements Serializable {
private static final long serialVersionUID = 1L;
// 私有化静态实例
private static Singleton03 s;
// 私有化构造方法
private Singleton03() {
// 避免反射破坏单例
if (null != s) {
throw new RuntimeException("No,you can't do this!");
}
}
// 提供全局访问点,只有初始化时需要进行同步
public static Singleton03 getInstance() {
if (null == s) {
Singleton03 singleton03;
synchronized (Singleton03.class) {
singleton03 = s;
if (null == singleton03) {
synchronized (Singleton03.class) {
if (null == singleton03) {
singleton03 = new Singleton03();
}
}
s = singleton03;
}
}
}
return s;
}
/**
*
* <method description>防止对象反序列化时破坏单例
*
* @return
* @throws ObjectStreamException
*/
private Object readResolve() throws ObjectStreamException {
return s;
}
}
4.静态内部类单例模式。
package com.zby.pattern;
import java.io.ObjectStreamException;
import java.io.Serializable;
/**
*
* <class description> 静态内部类单例模式 优点:线程安全,延迟加载。
* 静态内部类在外部类加载的时候不会被加载,而是在用到的时候才会被加载,所以可以延迟加载。
* @author: zby
* @version: 1.0, 2017年6月22日
*/
public class Singleton04 implements Serializable {
private static final long serialVersionUID = 1L;
// 私有化构造方法
private Singleton04() {
// 避免反射破坏单例
if (null != SingletonClassInstance.s) {
throw new RuntimeException("No,you can't do this!");
}
}
// 静态内部类,初始化静态实例对象
private static class SingletonClassInstance {
private static final Singleton04 s = new Singleton04();
}
public static Singleton04 getInstance() {
return SingletonClassInstance.s;
}
/**
*
* <method description>防止对象反序列化时破坏单例
*
* @return
* @throws ObjectStreamException
*/
private Object readResolve() throws ObjectStreamException {
return SingletonClassInstance.s;
}
}
5.枚举单例模式。
package com.zby.pattern;
import java.io.ObjectStreamException;
import java.io.Serializable;
/**
*
* <class description> 枚举单例模式 优点:从JVM根本上保证单例,避免反射和反序列化破坏。缺点:不能延迟加载。
* 可以参考枚举父类的源码:java.lang.Enum<E>
* @author: zby
* @version: 1.0, 2017年6月22日
*/
public enum Singleton05 {
INSTANCE;
}
总结:
效率:看代码就能看出进行同步的效率肯定低于非同步的。