在前两天的学习中主要对单例模式完成了五种实现,并针对反射及反序列化漏洞进行防止,最后对五种实现模式的效率进行测试。
五种最终实现单例模式代码如下:
1、懒汉式实现单例模式:
package com.zwh.gof23.singleton;
import java.io.Serializable;
/**
* 懒汉式到单例模式(防序列化及反射漏洞)
* @author zwh
* 特点:
* 1、延迟加载,在调用到getInstance方法时才加载。资源利用率高
* 2、调用getInstance方法时需要同步,并发效率较低
*/
public class SingletonPatternSlackerNew implements Serializable{
//实例不初始化,需要时再进行初始化
private static SingletonPatternSlackerNew instance;
private static int count = 0;
//私有化构造器
private SingletonPatternSlackerNew(){
synchronized (SingletonPatternSlackerNew.class) {
if(count > 0){
throw new RuntimeException("创建了两个实例");
}
count++;
}
//多次调用时,抛出异常
if(instance!=null){
throw new RuntimeException("已存在实例,别想用反射来搞我!");
}
}
/**
* 初始化类的实例,并保证在调用本方法时才会创建实例,保证线程安全。
* @return
*/
public static synchronized SingletonPatternSlackerNew getInstance(){
if(null == instance){
instance = new SingletonPatternSlackerNew();
}
return instance;
}
/**
* 防止被反序列化破解单例
* @return
*/
private Object readResolve(){
return instance;
}
}
2、饿汉式单例模式实现:
package com.zwh.gof23.singleton;
/**
* 单例模式(饿汉式)
* 1、构造器私有化
* 2、类初始化时立即加载。
* 特点:
* 1、线程安全
* 2、调用效率高
* 3、不能延时加载
* @author zwh
*
*/
public class SingletonPatternStarving {
//类初始化时就加载这个对象(static关键字),此时不涉及多个线程对象访问该对象的问题,
//虚拟机保证只会加载一次该类,肯定不会发生并发访问的问题。
//但是如果只是加载本类,而不是要调用geiInstance(),甚至永远没有使用,则造成资源浪费
private static SingletonPatternStarving instanse=new SingletonPatternStarving();
//构造器私有化
private SingletonPatternStarving(){
}
public static SingletonPatternStarving getInstance(){
return instanse;
}
}
3、双重检测锁实现单例模式:
package com.zwh.gof23.singleton;
/**
* 双重检测锁单例模式 将同步内容放到if条件内,只有第一次创建实例时需要进行同步,提高效率
*
* @author zwh
*
*/
public class SingletonPatternDoubleCheckLock {
// 声明变量
private static SingletonPatternDoubleCheckLock instance;
/**
* 全局访问方法,获取类的实例
*
* @return
*/
public static SingletonPatternDoubleCheckLock getInstance() {
if (null == instance) {
SingletonPatternDoubleCheckLock sc;
synchronized (SingletonPatternDoubleCheckLock.class) {
sc=instance;
if(null==sc){
synchronized (SingletonPatternDoubleCheckLock.class) {
if(null==sc){
sc=new SingletonPatternDoubleCheckLock();
}
}
instance=sc;
}
}
}
return instance ;
}
// 私有化构造器
private SingletonPatternDoubleCheckLock() {
}
}
4、静态内部类实现单例模式:
package com.zwh.gof23.singleton;
/**
* 静态内部类实现单利模式
* 1、只有调用全局访问方法时,才会初始化单例对象。可以延迟加载
* 2、加载类时天然的线程安全
* 3、同时具备懒汉式和饿汉式的优势
*
* @author zwh
*
*/
public class SingletonPatternInnerStaticClass {
/**
* 静态内部类中声明并初始化外部类的实例
*
* @author zwh
*
*/
private static class SingletonClassInstance {
private static final SingletonPatternInnerStaticClass instance =
new SingletonPatternInnerStaticClass();
}
/**
* 全局获取单例的方法
*
* @return
*/
public static SingletonPatternInnerStaticClass getInstance() {
return SingletonClassInstance.instance;
}
/**
* 构造方法私有化
*/
private SingletonPatternInnerStaticClass() {
}
}
5、枚举实现单例模式:
package com.zwh.gof23.singleton;
/**
* 使用枚举实现单例模式
* @author zwh
* 1、调用效率高
* 2、避免反射漏洞
* 3、没有延迟加载
*/
public enum SingletonPatternEnum {
/**
* 定义一个元素,代表一个实例
*/
INSTANCE;
/**
* 对枚举元素的操作
*/
public void singletonOperation(){
}
}
测试代码:
package com.zwh.gof23.singleton;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.CountDownLatch;
/**
* 单例模式测试类,测试不同实现方式的效率
* @author zwh
*
*/
public class TestClientForEffictive {
final static int threadNum=100;
public static void main(String[] args) throws InterruptedException {
testSingletonPatternSlackerNew();
testSingletonPatternStarving();
testSingletonPatternDoubleCheckLock();
testSingletonPatternInnerStaticClass();
testSingletonPatternEnum();
}
/**
* 测试懒汉式单例模式效率
* @throws InterruptedException
*/
private static void testSingletonPatternSlackerNew() throws InterruptedException{
final CountDownLatch countDownLatch=new CountDownLatch(threadNum);
long start=System.currentTimeMillis();
for(int i=0;i<threadNum;i++){
new Thread(new Runnable() {
public void run() {
for(int i=0;i<100000;i++){
SingletonPatternSlackerNew instance=SingletonPatternSlackerNew.getInstance();
}
countDownLatch.countDown();
}
}).start();
}
countDownLatch.await();
long end=System.currentTimeMillis();
System.out.println("懒汉式单例模式实现耗时:"+(end-start));
}
/**
* 测试饿汉式单例模式效率
* @throws InterruptedException
*/
private static void testSingletonPatternStarving() throws InterruptedException{
final CountDownLatch countDownLatch=new CountDownLatch(threadNum);
long start=System.currentTimeMillis();
for(int i=0;i<threadNum;i++){
new Thread(new Runnable() {
public void run() {
for(int i=0;i<100000;i++){
SingletonPatternStarving instance=SingletonPatternStarving.getInstance();
}
countDownLatch.countDown();
}
}).start();
}
countDownLatch.await();
long end=System.currentTimeMillis();
System.out.println("饿汉式单例模式实现耗时:"+(end-start));
}
/**
* 测试双重检测锁实现的单例模式效率
* @throws InterruptedException
*/
private static void testSingletonPatternDoubleCheckLock() throws InterruptedException{
final CountDownLatch countDownLatch=new CountDownLatch(threadNum);
long start=System.currentTimeMillis();
for(int i=0;i<threadNum;i++){
new Thread(new Runnable() {
public void run() {
for(int i=0;i<100000;i++){
SingletonPatternDoubleCheckLock instance=SingletonPatternDoubleCheckLock.getInstance();
}
countDownLatch.countDown();
}
}).start();
}
countDownLatch.await();
long end=System.currentTimeMillis();
System.out.println("双重检测锁式单例模式实现耗时:"+(end-start));
}
/**
* 测试静态内部类实现的单例模式效率
* @throws InterruptedException
*/
private static void testSingletonPatternInnerStaticClass() throws InterruptedException{
final CountDownLatch countDownLatch=new CountDownLatch(threadNum);
long start=System.currentTimeMillis();
for(int i=0;i<threadNum;i++){
new Thread(new Runnable() {
public void run() {
for(int i=0;i<100000;i++){
SingletonPatternInnerStaticClass instance=SingletonPatternInnerStaticClass.getInstance();
}
countDownLatch.countDown();
}
}).start();
}
countDownLatch.await();
long end=System.currentTimeMillis();
System.out.println("静态内部类式单例模式实现耗时:"+(end-start));
}
/**
* 测试枚举实现的单例模式效率
* @throws InterruptedException
*/
private static void testSingletonPatternEnum() throws InterruptedException{
final CountDownLatch countDownLatch=new CountDownLatch(threadNum);
long start=System.currentTimeMillis();
for(int i=0;i<threadNum;i++){
new Thread(new Runnable() {
public void run() {
for(int i=0;i<100000;i++){
SingletonPatternEnum instance=SingletonPatternEnum.INSTANCE;
}
countDownLatch.countDown();
}
}).start();
}
countDownLatch.await();
long end=System.currentTimeMillis();
System.out.println("枚举式单例模式实现耗时:"+(end-start));
}
}
输出结果:
懒汉式单例模式实现耗时:209
饿汉式单例模式实现耗时:21
双重检测锁式单例模式实现耗时:25
静态内部类式单例模式实现耗时:31
枚举式单例模式实现耗时:25
不同环境测试结果可能不同,此结果仅供参考。可得出懒汉式单例模式实现效率最低