单例模式

一:单例模式作用:
	核心作用:保证一个类只有一个实例,并且提供一个访问该实例的全局访问点。
	
二:单例模式的优点:
	1、由于单例模式只生成一个实例,减少了系统的性能开销,当一个对象的产生需要比较多的
		资源时,如读取配置,产生其他依赖对象时,则可以通过在应用启动时直接产生一个单例
		对象,然后永久驻留内存的方式来解决。
	2、单例模式可以在系统设置全局的访问点,优化共享资源访问,例如可以设计一个单例类
		负责所有数据表的映射处理。


三:常见的5中单例模式实现方式
	主要:
	1、饿汉式(线程安全、调用效率高、但是不能延时加载)
	2、懒汉式(线程不安全、调用效率不高、但是可以延时加载)
	其他:
	1、双重检测锁式(由于JVM底层内部模型的原因,偶尔会出问题,不建议使用)
	2、静态内部类式(线程安全、调用效率高、可以延时加载)
	3、枚举单例(线程安全、调用效率高、但不能延时加载)
	不需要延时加载:枚举好于饿汉
	需要延时加载:静态内部类好于懒汉
1、饿汉式:
package com.chen.Singleton;
/**
 * 饿汉式单例模式
 *1、私有化构造器
 *2、创建对象
 *3、提供静态方法获得实例对象
 *  不用加synchronized,饿汉式天生线程安全,但不能延时加载,加载类时就实例化对象
 * @author Administrator
 *
 */
public class SingletonDemo01 {

	// 2、创建对象
	private static SingletonDemo01 instance = new SingletonDemo01();
	
	// 1、私有化构造器
	private SingletonDemo01() {
		
	}
	// 3、提供静态方法获得实例对象
	public static SingletonDemo01 getInstance() {
		
		return instance;
	}
}
2、懒汉式:
package com.chen.Singleton;
/**
 * 懒汉式单例模式,和恶汉式差不多,不同点在于,
 * 需要加synchronized来保证单例,可以延时加载
 * @author Administrator
 *
 */
public class SingletonDemo02 {

	private static SingletonDemo02 instance;
	
	private SingletonDemo02() {
		
	}
	
	public static synchronized SingletonDemo02 getInstance() {
		
		if(instance == null) {
			
			instance = new SingletonDemo02();
		}
		return instance;
	} 
}

3、静态内部类式:
package com.chen.Singleton;
/**
 * 静态内部类实现单例模式
 * 兼并了饿汉式和懒汉式的优点,线程安全,效率高,可以延时加载
 * @author Administrator
 *
 */
public class SingletonDemo03 {

	private static class SingletonInstance {
		
		private static final SingletonDemo03 instance = new SingletonDemo03();
	}
	
	private SingletonDemo03() {
		
		
	}
	
	public static SingletonDemo03 getInstance() {
		
		return SingletonInstance.instance;
	}
}

4、枚举实现单例模式:
package com.chen.Singleton;
/**
 * 枚举实现单例模式
 * 唯一缺点:不能延时加载
 * 相比其他单例模式:解决了反射、序列化带来的问题
 * @author Administrator
 *
 */
public enum SingletonDemo04 {

	// 枚举类型,本身就是一个单例模式
	INSTANCE;
	
	
	// 添加自己的操作....
	public void test() {
		
		System.out.println("你好啊!!!");
	}
}

测试:
package com.chen.Singleton;
/**
 * 测试单例模式
 * @author Administrator
 *
 */
public class Test {

	public static void main(String[] args) {
		
		test01();
	}
	
	public static void test01() {
		
		SingletonDemo01 instance = SingletonDemo01.getInstance();
		SingletonDemo01 instance2 = SingletonDemo01.getInstance();
		System.out.println(instance);
		System.out.println(instance2);
		
		
		// 枚举类型的调用
		SingletonDemo04 instance3 = SingletonDemo04.INSTANCE;
		System.out.println(instance3);
		instance3.test();
	}
}

测试各种单例模式的效率:
package com.chen.Singleton;

import java.util.concurrent.CountDownLatch;

/**
 * 测试各种单例模式的效率
 * CountDownLatch:同步辅助类
 * countDown() 当前线程调用该方法,则计数器减一(建议放在finally中执行)
 * await() 调用该方法会一直阻塞线程,直到计数器为0
 * 
 * 测试结果:
 * 懒汉式用时比恶汉多大约两个数量级
 * @author Administrator
 *
 */
public class Test_Effective {

	public static void main(String[] args) throws Exception {
		
		long startTime = System.currentTimeMillis();
		int threadNum = 10;
		// 计数器初始值为10
		// 不加final内部类中无法访问
		final CountDownLatch count = new CountDownLatch(threadNum);
		
		// 创建10个线程
		for(int i = 0; i < threadNum; i++) {
			
			new Thread(new Runnable(){
				
				@Override
				public void run() {
					
					for(int i = 0; i < 10000000; i++) {
						// 01变为02就可以测试第二种的效率了。
						SingletonDemo01 instance = SingletonDemo01.getInstance();
					}
					
					// 每个线程执行完成,计数器减一
					count.countDown();
				}
			}).start();
		}
		
		// main线程等待,直到计数器为0才开始往下执行
		count.await();
		
		long endTime = System.currentTimeMillis();
		
		System.out.println("耗时:"+(endTime - startTime)+"ms");
	}
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值