如何实现Singleton模式
发表于:2025-01-24 作者:千家信息网编辑
千家信息网最后更新 2025年01月24日,如何实现Singleton模式,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。题目设计一个类,我们只能生成该类的一个实例分
千家信息网最后更新 2025年01月24日如何实现Singleton模式
如何实现Singleton模式,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
题目
设计一个类,我们只能生成该类的一个实例
分析
最简单实现
私有构造方法
静态方法获取实例
是否需要考虑内存或并发环境
如果需要考虑内存,使用到时才创建实例对象(饿汉),不使用时就不创建实例(懒汉,懒加载)。
如果需要考虑线程安全,就要确保获取实例是同步的,避免创建多个实例。
实现方式
[x] 1. 单线程(懒汉式、饿汉式)
[x] 2. 多线程工作效率不高(加锁获取实例的方法)
[x] 3. 加同步锁前后两次判断实例是否已存在
[x] 4. 利用静态初始化创建实例(推荐,线程安全,会占用一部分内存)
[x] 5. 利用静态内部类实现按需创建实例(最推荐,线程安全,效率高,聪明的你应该可以明白的)
编码实现
1. 单线程(懒汉式、饿汉式)
饿汉单例
package cn.jast.java.offer.singleton;/** * 简单饿汉单例 * */public class SimpleHungerSingleton { private static SimpleHungerSingleton simpleSingleton; private SimpleHungerSingleton(){ simpleSingleton = new SimpleHungerSingleton(); } public static SimpleHungerSingleton getInstance(){ return simpleSingleton; }}
简单懒汉单例
package cn.jast.java.offer.singleton;/** * 简单懒汉单例 * */public class SimpleLazySingleton { private static SimpleLazySingleton simpleSingleton; private SimpleLazySingleton(){ } public static SimpleLazySingleton getInstance(){ if(simpleSingleton == null){ simpleSingleton = new SimpleLazySingleton(); } return simpleSingleton; }}
线程安全测试
/** * 测试简单单例的线程安全 */ public static void testSimpleLazySingleton(){ SetsingletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ SimpleLazySingleton simpleLazySingleton = SimpleLazySingleton.getInstance(); singletonSet.add(simpleLazySingleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ if(singletonSet.size()>1){ System.out.println("简单单例存在创建多个实例对象,实例如下:"); System.out.println(singletonSet); } break; } } }
输出:
简单单例存在创建多个实例对象,实例如下:[cn.jast.java.offer.singleton.SimpleLazySingleton@2b9283d, cn.jast.java.offer.singleton.SimpleLazySingleton@72fba635]
2. 多线程工作效率不高(加锁获取实例的方法)
package cn.jast.java.offer.singleton;public class Synchronized1Singleton { private static Synchronized1Singleton instance; private Synchronized1Singleton(){ } /** * 每次获取对象时都加锁来确保创建对象 * @return */ public static synchronized Synchronized1Singleton getInstance(){ if(instance == null){ instance = new Synchronized1Singleton(); } return instance; }}
测试:
public static void testSynchronized1Singleton(){ long startTime = System.currentTimeMillis(); SetsingletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ Synchronized1Singleton singleton = Synchronized1Singleton.getInstance(); singletonSet.add(singleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ System.out.println(String.format("执行时间:%s ms",System.currentTimeMillis()-startTime)); if(singletonSet.size()>1){ System.out.println("简单单例存在创建多个实例对象,实例如下:"); System.out.println(singletonSet); } break; } } }
输出:
执行时间:72 ms(注:一个样例)
3. 加同步锁前后两次判断实例是否已存在
package cn.jast.java.offer.singleton;public class Synchronized2Singleton { private static Synchronized2Singleton instance; private Synchronized2Singleton(){ } public static Synchronized2Singleton getInstance(){ if(instance == null){ synchronized (Synchronized2Singleton.class){ if(instance==null){ instance = new Synchronized2Singleton(); } } } return instance; }}
4. 利用静态初始化创建实例(推荐,线程安全)
package cn.jast.java.offer.singleton;/** * 推荐 */public class StaticInitializeSingleton { private static StaticInitializeSingleton instance ; static{ instance = new StaticInitializeSingleton(); } private StaticInitializeSingleton(){ } public static StaticInitializeSingleton getInstance(){ return instance; }}
5. 利用静态内部类实现按需创建实例(最推荐,线程安全,效率高)
package cn.jast.java.offer.singleton;/** * 推荐 */public class StaticInnerClassSingleton { private StaticInnerClassSingleton(){ } public static StaticInnerClassSingleton getInstance(){ return Inner.instance; } private static class Inner{ private static final StaticInnerClassSingleton instance = new StaticInnerClassSingleton(); }}
完整的测试
package cn.jast.java.offer.singleton;import java.util.*;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;public class Main { public static void main(String[] args) {// testSimpleLazySingleton(); testSynchronized1Singleton();// testSynchronized2Singleton();// testStaticInitializeSingleton();// testNestedClassSingleton(); } /** * 测试简单单例的线程安全 */ public static void testSimpleLazySingleton(){ SetsingletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ SimpleLazySingleton simpleLazySingleton = SimpleLazySingleton.getInstance(); singletonSet.add(simpleLazySingleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ if(singletonSet.size()>1){ System.out.println("简单单例存在创建多个实例对象,实例如下:"); System.out.println(singletonSet); } break; } } } /** * 测试线程安全的单例模式实现 */ public static void testSynchronized1Singleton(){ long startTime = System.currentTimeMillis(); Set singletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ Synchronized1Singleton singleton = Synchronized1Singleton.getInstance(); singletonSet.add(singleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ System.out.println(String.format("执行时间:%s ms",System.currentTimeMillis()-startTime)); if(singletonSet.size()>1){ System.out.println("简单单例存在创建多个实例对象,实例如下:"); System.out.println(singletonSet); } break; } } } /** * Synchronized2Singleton 的效率比 Synchronized1Singleton高几倍甚至几十倍以上 */ public static void testSynchronized2Singleton(){ long startTime = System.currentTimeMillis(); Set singletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ Synchronized2Singleton singleton = Synchronized2Singleton.getInstance(); singletonSet.add(singleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ System.out.println(String.format("执行时间:%s ms",System.currentTimeMillis()-startTime)); if(singletonSet.size()>1){ System.out.println("简单单例存在创建多个实例对象,实例如下:"); System.out.println(singletonSet); } break; } } } /** * */ public static void testStaticInitializeSingleton(){ Set singletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ Synchronized2Singleton singleton = Synchronized2Singleton.getInstance(); singletonSet.add(singleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ if(singletonSet.size()>1){ System.out.println("简单单例存在创建多个实例对象,实例如下:"); System.out.println(singletonSet); } break; } } } public static void testNestedClassSingleton(){ Set singletonSet = Collections.synchronizedSet(new HashSet<>()); ExecutorService executorService = Executors.newFixedThreadPool(50); for (int i = 0; i < 10; i++) { executorService.submit(()->{ StaticInnerClassSingleton singleton = StaticInnerClassSingleton.getInstance(); singletonSet.add(singleton); }); } executorService.shutdown(); while(true){ if(executorService.isShutdown()){ if(singletonSet.size()>1){ System.out.println("简单单例存在创建多个实例对象,实例如下:"); System.out.println(singletonSet); } break; } } }}
自问自答
问:单例模式获取实例的方法为什么是静态方法? 答:因为构造方法是私有的,无法通过new创建实例,那只能通过类方法获取实例。那通过反射是否可以创建实例呢?
看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注行业资讯频道,感谢您对的支持。
实例
线程
对象
安全
多个
方法
静态
推荐
测试
懒汉
效率
时间
模式
同步
内存
工作
帮助
私有
输出
清楚
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
打不开视频软件开发
mysql数据库big
四川工程软件开发多少钱
数据库 复制列
数据库审计与安全审计
服务器管理app
网络安全工程专业有什么课程
奥比岛手游服务器问题
长宁区无线网络技术有哪些
网络安全 课程设置
应用对接多个数据库坏处
国泰安数据库不能查美股吗
永州游戏软件开发价格
做软件开发和编程有啥区别吗
湖南hp服务器虚拟化定制
服务器自带的网络打印机怎么用
服务器开机按键图解
中望软件开发单位
什么叫金融信息基础数据库
电网网络安全 文件
网络技术安全发展现状和趋势
阿里云查看服务器在线人数
网构软件开发内容
中国通用集团软件开发
浅析网络安全发展论文
关系型数据库表的正确说法
怎样才能运用大数据库
润衡软件数据库类型及版本
网络安全管理局 英文
软件开发中日志功能怎么设计