如何实现Singleton模式
发表于:2025-12-02 作者:千家信息网编辑
千家信息网最后更新 2025年12月02日,如何实现Singleton模式,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。题目设计一个类,我们只能生成该类的一个实例分
千家信息网最后更新 2025年12月02日如何实现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(){ Set singletonSet = 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(); 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; } } } 输出:
执行时间: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(){ Set singletonSet = 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安全错误
数据库的锁怎样保障安全
央视大学生网络安全
远程数据库本地同步软件
虚拟视频软件开发
服务器管理器增加角色
软件开发商公司拖进度怎么办
提高软件开发效率应该尽量采用
网络技术中级职称考试科目
郑州非特网络技术怎么样
北京软件开发的国企
税控服务器管理系统使用流程
家用服务器怎么保护
税局网络安全等级保护
蓬莱定制软件开发推荐
华为服务器型号代表什么意思
云服务器安装ftp
构建数据库开发环境
企业网络安全知识宣传片
php采集页面存入数据库
学生办网络安全的手抄报
空中比特币俱乐部服务器安全
网络安全新局面新要求
mysql表清空数据库表
网络安全周答题有奖励吗
河南工控软件开发大概多少钱
合成大数据库
云南教育扶贫数据库能导入吗
江西商业软件开发价格大全
网络安全征集评奖
软件开发基金代码有哪些
丰台区网络技术开发概况