单例模式

单例模式(Singleton pattern)
核心作用:

确保一个类只有一个实例对象, 并提供一个访问该实例的全局访问点

应用场景:

1:Windows的Task Manager(任务管理器)。用户只能打开一个任务管理器

2:Windows的Recycle Bin(回收站)。在系统运行过程中,也只能打开一个

3:项目中,读取配置文件的类。一般只有一个对象,没有必要每次使用配置文件数据,每次new一个对象去读取

4:网站的计数器。一般采用单例模式实现,否则难以同步

5:应用程序的日志应用。由于共享的日志文件一直处于打开状态,只能有一个实例去操作,否则内容不好追加

6:数据库连接池。数据库连接是一种数据库资源

7:操作系统的文件系统。一个操作系统只能有一个文件系统

8:Application(Servlet编程)

9:在Servlet编程中,每个Servlet也是单例

10:在Spring中,每个Bean默认就是单例。这样做优点是Spring容器可以管理

11:在Spring MVC框架/Struts1框架中,控制器对象也是单例

优点:

1:由于一个单例模式只生成一个实例,减少了系统性能开销。当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用程序中直接产生一个单例对象,然后永久驻留内存的方式来解决

2:单例模式可以在系统设置全局的访问点,优化共享资源访问,例如可以设计一个单例类,负责所有数据表的映射处理

常见单例模式实现方式:

1:主要方式 

     恶汉式(线程安全,调用效率高。但是,不能延时加载)

     懒汉式(线程安全,调用效率不高。但是,可以延时加载)

2:其他方式

     双重检查锁式(由于JVM底层内部模型原因,偶尔会出问题,不建议使用)

     静态内部类方式(线程安全,调用效率低。但是,可以延时加载)

     枚举式(线程安全,调用效率高。但是,不能延时加载,但可以天然的防止反射和反序列化漏洞)

恶汉式(立即加载,刚开始定义静态成员变量,便加载):

/*
 * 单例模式之恶汉式
 * 步骤1:创建类的私有构造器
 * 步骤2:创建类的私有静态成员对象,并直接调用私有构造器初始化
 * 步骤3:创建类的公有方法,返回该静态成员对象的实例
 */

public class SingletonOfHungry {
	
	//2:创建类的私有静态成员对象,并直接调用私有构造器传值初始化
	private static SingletonOfHungry singleton = new SingletonOfHungry();
	
	//1:创建类的私有构造器
	private SingletonOfHungry(){
	
	}
	
	//3:创建类的公有方法,返回该静态成员对象的实例
	public static SingletonOfHungry getInstance(){
		return singleton;
	}
}

懒汉式(延迟加载,只有用的时候才加载):

/*
 * 单例模式之懒汉式式
 * 步骤1:创建类的私有构造器
 * 步骤2:创建类的私有静态成员对象
 * 步骤3:创建类的公有方法,返回该静态成员对象的实例,(需要同步,防止高并发时,产生多个实例对象)
 */

public class SingletonOfLazy {
	
	//2:创建类的私有静态成员对象
	private static SingletonOfLazy singleton;
	
	//1:创建类的私有构造器
	private SingletonOfLazy(){
		
	}
	
	//3:创建类的公有方法,返回该静态成员对象的实例,(需要同步,防止高并发时,产生多个实例对象)
	public static synchronized SingletonOfLazy getInstance(){
		if(singleton == null){
			singleton = new SingletonOfLazy();
		}
		return singleton;
	}
}

双重检查锁式(把同步块更加细节化,但存在一定问题,不建议使用):

/*
 * 单例模式之双重检测锁式
 * 核心思想:将懒汉式中的同步方法进一步细化,由于同步调用顺序等问题,偶尔会出问题,不建议使用
 */

public class SingletonOfDoubleLock {
		private static SingletonOfDoubleLock singleton = null;
		
		private SingletonOfDoubleLock(){
			
		}
		
		public static SingletonOfDoubleLock getInstance(){
			if(singleton == null){
				SingletonOfDoubleLock sod;
				synchronized (SingletonOfDoubleLock.class) {
					sod = singleton;
					if(sod == null){
						synchronized (SingletonOfDoubleLock.class) {
							if(sod == null){
								sod = new SingletonOfDoubleLock();
							}
						}
						singleton = sod;
					}
				}
			}
			return singleton;
		}
}

静态内部类式(兼备了并发高效调用和延迟加载的优势):

/*
 * 单例模式之静态内部类方式
 * 核心思想:将实例对象的产生封装在私有内部类中,这样外部类没有static属性,不会像恶汉式那样立即加载
 */

public class SingletonOfStaticInnerClass {
		//内部类
		private static class SingletonInner{
			private static SingletonOfStaticInnerClass singleton = new SingletonOfStaticInnerClass();
			}
		
		//私有构造器
		private SingletonOfStaticInnerClass(){
			
		}
		
		//公有方法返回内部类中的静态成员,没有同步
		public static SingletonOfStaticInnerClass getIntance(){
			return SingletonInner.singleton;
		}
}

枚举式(枚举元素本身就是一个单例,没有延时加载):

/*
 * 单例模式之枚举式
 * 核心思想:枚举元素本身就是一个单例
 */

public enum SingletonOfEnum {
	
	//这个枚举元素本身就是一个单例
	INSTANCE;
	
	//可以加入自己的方法
	public void selfOperation(){
		
	}
}
测试:
public class SingletonTest {

	public static void main(String[] args) {
		SingletonOfDoubleLock s1 = SingletonOfDoubleLock.getInstance();
		SingletonOfDoubleLock s2 = SingletonOfDoubleLock.getInstance();
		System.out.println(s1);
		System.out.println(s2);
		System.out.println(SingletonOfEnum.INSTANCE == SingletonOfEnum.INSTANCE);
	}

}

console:
com.java.patterns.SingletonOfDoubleLock@2e739136
com.java.patterns.SingletonOfDoubleLock@2e739136
true
拓展思考(不包含枚举式):

Q:这样写真的足够安全吗?

答案是否定的,别忘记了反射的暴力破解,通过c.setAccessible(true),可以绕过权限检查直接调用私有构造器

解决方案:为此我们可以在私有构造方法中加入判断,如果当前不是第一次调用构造器,就向外抛出异常,终止程序运行

	//在私有构造方法中加入判断
	private SingletonOfHungry(){
		//防止反射的暴力破解
		if(singleton != null){
			throw new RuntimeException("创建失败");
		}
	}
延伸拓展思考(不包含枚举式):

Q:解决了反射的暴力破解,就真的足够安全吗?

答案是否定的,别忘记了序列化与反序列化的漏洞,当对象被ObjectOutputStream写入文件中,当反序列化的时候ois.readObject()依然会产生一个新的实例

解决方案:在单例模式中重写readResolve()方法,返回此方法指定对象,而不需要再重新创建新对象

	//防止序列化与反序列化的漏洞
	private Object readResolve() throws ObjectStreamException{
		return singleton;
	}

几种单例模式效率比较(懒汉式由于采用同步方式,效率最低):
public class SingletonTimeCompare {
	public static void main(String[] args) {
		//获取系统开始时间
		long start = System.currentTimeMillis();
		//创建线程计数器,以解决main与多线程并行运算时,线程还没有结束,系统结束时间已经结束的问题
		int threadCount = 8;
		final CountDownLatch count = new CountDownLatch(threadCount);
		
		// 采用循环多建立几组线程
		for (int i = 0; i < threadCount; i++) {

			// 采用匿名内部类创建线程,创建多组单例对象
			new Thread(new Runnable() {

				public void run() {
					for (int i = 0; i < 100000; i++) {
						SingletonOfHungry singleton = SingletonOfHungry
								.getInstance();
//						SingletonOfLazy singleton = SingletonOfLazy.getInstance();
					}
					//当前线程调用此方法时,则计数减1
					count.countDown();
				}
			}).start();
		}
		//调用此方法会一直阻塞当前线程(此处为main主线程),直到计数器减为0
		try {
			count.await();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		//获取线程结束时系统开始时间
		long end = System.currentTimeMillis();
		System.out.println("该单例模式共耗时:" + (end - start));
	}
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值