【设计模式】单例模式 在java中的应用
文章目录
- 引言
- 什么是单例模式
- 单例模式的应用场景
- 单例模式的优缺点
- 优点
- 缺点
- 单例模式的基本实现
- 饿汉式单例模式
- 懒汉式单例模式
- 双重检查锁定
- 静态内部类
- 枚举单例
- 单例模式的线程安全问题
- 多线程环境下的单例模式
- 线程安全的实现方式
- 1. **懒汉式单例模式(线程不安全)**
- 2. **懒汉式单例模式(线程安全,使用同步方法)**
- 3. **双重检查锁定**
- 4. **静态内部类**
- 5. **枚举单例**
- 单例模式的序列化与反序列化
- 序列化导致的问题
- 如何防止反序列化破坏单例
- 单例模式的反射攻击
- 反射攻击导致的问题
- 如何防止反射破坏单例
- 使用枚举类型防止反射和序列化攻击
- 单例模式的实际应用案例
- 数据库连接池管理
- 日志管理
- 配置文件管理
- 总结
- 单例模式的最佳实践
- 单例模式的使用建议
引言
什么是单例模式
单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问该实例。单例模式通过控制实例化过程来避免创建多个实例,从而节省资源并确保全局状态的一致性。
在 Java 中,实现单例模式的核心思想是私有化构造方法,并通过一个公共的静态方法来返回类的唯一实例。
单例模式的应用场景
单例模式适用于以下场景:
- 资源管理器:如线程池、数据库连接池等,这些资源通常是重量级的,频繁创建和销毁会带来性能开销,因此需要一个全局唯一的实例来管理这些资源。
- 配置管理:应用程序的配置文件通常是全局唯一的,使用单例模式可以确保配置的唯一性和一致性。
- 日志记录器:日志记录器在整个应用程序中通常是唯一的,使用单例模式可以确保日志记录的统一性和线程安全性。
- 缓存:缓存数据通常需要全局唯一的实例来管理,以便在不同的地方访问和修改缓存时保持一致性。
单例模式的优缺点
优点
- 控制实例数量:确保一个类只有一个实例,避免了实例的重复创建,节省系统资源。
- 全局访问点:提供一个全局访问点,使得访问该实例变得简单。
- 延迟加载:某些实现方式(如懒汉式单例)可以实现延迟加载,即在需要时才创建实例,从而提高系统性能。
缺点
- 不易扩展:由于单例类的构造方法是私有的,继承和扩展变得困难。
- 隐藏依赖关系:单例模式隐藏了类之间的依赖关系,增加了代码的复杂性和维护难度。
- 多线程问题:在多线程环境下实现单例模式时,需要考虑线程安全问题,否则可能会创建多个实例。
单例模式的基本实现
饿汉式单例模式
饿汉式单例模式在类加载时就创建实例,确保类在第一次引用时就已经实例化。
public class HungrySingleton {// 类加载时就创建实例private static final HungrySingleton instance = new `();// 私有构造方法,防止外部实例化private HungrySingleton() {}// 提供公共的静态方法获取实例public static HungrySingleton getInstance() {return instance;}
}
优点:
- 实现简单。
- 线程安全,因为实例在类加载时就创建了。
缺点:
- 如果实例占用资源较多且未被使用,会造成资源浪费。
懒汉式单例模式
懒汉式单例模式在第一次需要使用实例时才创建,避免了资源浪费。
public class LazySingleton {// 静态变量保存单例实例private static LazySingleton instance;// 私有构造方法,防止外部实例化private LazySingleton() {}// 提供公共的静态方法获取实例public static LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}
}
优点:
- 延迟加载,只有在需要时才创建实例。
缺点:
- 线程不安全,多线程环境下可能会创建多个实例。
双重检查锁定
双重检查锁定在懒汉式单例模式的基础上,使用同步块和双重检查机制来保证线程安全。
public class DoubleCheckedLockingSingleton {// volatile 确保 instance 的可见性和有序性private static volatile DoubleCheckedLockingSingleton instance;// 私有构造方法,防止外部实例化private DoubleCheckedLockingSingleton() {}// 提供公共的静态方法获取实例public static DoubleCheckedLockingSingleton getInstance() {if (instance == null) {synchronized (DoubleCheckedLockingSingleton.class) {if (instance == null) {instance = new DoubleCheckedLockingSingleton();}}}return instance;}
}
优点:
- 线程安全。
- 延迟加载,性能较好。
缺点:
- 实现较为复杂,需要理解 volatile 关键字和双重检查机制。
静态内部类
静态内部类方式利用 JVM 类加载机制来保证线程安全,同时实现延迟加载。
public class StaticInnerClassSingleton {// 私有构造方法,防止外部实例化private StaticInnerClassSingleton() {}// 静态内部类private static class SingletonHolder {private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();}// 提供公共的静态方法获取实例public static StaticInnerClassSingleton getInstance() {return SingletonHolder.INSTANCE;}
}
优点:
- 线程安全。
- 延迟加载。
- 实现简单,利用 JVM 的类加载机制,避免了同步开销。
缺点:
- 无法提前创建实例。
枚举单例
枚举单例利用枚举类型本身的特性来保证单例模式的实现,是最简单且最安全的实现方式。
public enum EnumSingleton {INSTANCE;// 可以添加其他方法public void someMethod() {// 方法实现}
}
优点:
- 线程安全。
- 防止反序列化破坏单例。
- 防止反射攻击。
缺点:
- 无法实现延迟加载(但通常不需要,因为 JVM 保证枚举类的唯一性)。
单例模式的线程安全问题
多线程环境下的单例模式
在多线程环境中,单例模式的实现需要特别注意线程安全问题。多个线程同时访问单例类的实例获取方法时,可能会导致创建多个实例,违背单例模式的初衷。为了确保单例模式在多线程环境下的正确性,需要采取一些措施来保证线程安全。
线程安全的实现方式
1. 懒汉式单例模式(线程不安全)
最简单的懒汉式单例实现并没有考虑线程安全,在多线程环境下可能会创建多个实例。
public class LazySingleton {private static LazySingleton instance;private LazySingleton() {}public static LazySingleton getInstance() {if (instance == null) {instance = new LazySingleton();}return instance;}
}
2. 懒汉式单例模式(线程安全,使用同步方法)
通过在 getInstance 方法上加 synchronized 关键字,确保每次只有一个线程能够执行该方法,从而保证线程安全。
public class SynchronizedLazySingleton {private static SynchronizedLazySingleton instance;private SynchronizedLazySingleton() {}public static synchronized SynchronizedLazySingleton getInstance() {if (instance == null) {instance = new SynchronizedLazySingleton();}return instance;}
}
优点:
- 简单易实现。
- 线程安全。
缺点:
- 每次调用
getInstance方法时都需要进行同步,性能开销较大。
3. 双重检查锁定
双重检查锁定在第一次检查实例是否为 null 时不加锁,只有在实例为 null 时才进行同步操作,从而减少了同步开销。
public class DoubleCheckedLockingSingleton {private static volatile DoubleCheckedLockingSingleton instance;private DoubleCheckedLockingSingleton() {}public static DoubleCheckedLockingSingleton getInstance() {if (instance == null) {synchronized (DoubleCheckedLockingSingleton.class) {if (instance == null) {instance = new DoubleCheckedLockingSingleton();}}}return instance;}
}
优点:
- 线程安全。
- 相比同步方法,性能更高。
缺点:
- 实现复杂,需要注意
volatile关键字的使用。
4. 静态内部类
利用 Java 的类加载机制,静态内部类在被调用时才会被加载,从而实现延迟加载和线程安全。
public class StaticInnerClassSingleton {private StaticInnerClassSingleton() {}private static class SingletonHolder {private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();}public static StaticInnerClassSingleton getInstance() {return SingletonHolder.INSTANCE;}
}
优点:
- 线程安全。
- 实现简单,延迟加载。
缺点:
- 无法防止反射攻击。
5. 枚举单例
枚举类型本身是线程安全的,并且枚举的实例是全局唯一的,可以防止反射和序列化导致的重新创建实例问题。
public enum EnumSingleton {INSTANCE;public void someMethod() {// some method}
}
优点:
- 线程安全。
- 防止反射和序列化导致的重新创建实例问题。
缺点:
- 枚举类型在某些情况下可能不适用(例如需要继承其他类)。
单例模式的序列化与反序列化
序列化导致的问题
在 Java 中,单例模式可能会由于序列化和反序列化而被破坏。具体来说,当一个单例对象被序列化到文件中,然后再从文件中反序列化回来时,会创建一个新的实例,这样就违反了单例模式的原则。
例如,考虑以下单例类:
import java.io.Serializable;public class Singleton implements Serializable {private static final long serialVersionUID = 1L;private static final Singleton instance = new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}
}
如果我们进行序列化和反序列化操作:
import java.io.*;public class SingletonSerializationTest {public static void main(String[] args) throws Exception {Singleton instanceOne = Singleton.getInstance();// 序列化对象到文件ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("singleton.ser"));out.writeObject(instanceOne);out.close();// 从文件中反序列化对象ObjectInputStream in = new ObjectInputStream(new FileInputStream("singleton.ser"));Singleton instanceTwo = (Singleton) in.readObject();in.close();System.out.println("instanceOne hashCode: " + instanceOne.hashCode());System.out.println("instanceTwo hashCode: " + instanceTwo.hashCode());}
}
输出可能会是两个不同的哈希码,表明反序列化创建了一个新的实例。
如何防止反序列化破坏单例
为了防止反序列化破坏单例,可以在单例类中实现 readResolve 方法。这个方法在反序列化时会被自动调用,返回当前的单例实例,从而确保反序列化不会创建新的实例。
import java.io.Serializable;public class Singleton implements Serializable {private static final long serialVersionUID = 1L;private static final Singleton instance = new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}// 添加 readResolve 方法protected Object readResolve() {return getInstance();}
}
现在,如果我们再次运行序列化和反序列化操作,输出将会是相同的哈希码,表明反序列化没有创建新的实例:
import java.io.*;public class SingletonSerializationTest {public static void main(String[] args) throws Exception {Singleton instanceOne = Singleton.getInstance();// 序列化对象到文件ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("singleton.ser"));out.writeObject(instanceOne);out.close();// 从文件中反序列化对象ObjectInputStream in = new ObjectInputStream(new FileInputStream("singleton.ser"));Singleton instanceTwo = (Singleton) in.readObject();in.close();System.out.println("instanceOne hashCode: " + instanceOne.hashCode());System.out.println("instanceTwo hashCode: " + instanceTwo.hashCode());}
}
通过实现 readResolve 方法,可以确保序列化和反序列化过程中不会破坏单例模式,从而维护单例的唯一性。
单例模式的反射攻击
反射攻击导致的问题
Java 的反射机制允许在运行时动态地创建对象、调用方法和访问字段。通过反射,可以绕过私有构造函数,直接创建单例类的新实例,从而破坏单例模式。
例如,考虑以下单例类:
public class Singleton {private static final Singleton instance = new Singleton();private Singleton() {}public static Singleton getInstance() {return instance;}
}
使用反射可以创建新的实例:
Singleton instance1 = Singleton.getInstance();Constructor<Singleton> constructor = Singleton.class.getDeclaredConstructor();
constructor.setAccessible(true);
Singleton instance2 = constructor.newInstance();System.out.println(instance1 == instance2); // 输出 false
如何防止反射破坏单例
为了防止反射攻击,可以在单例类的构造函数中加入防御措施,确保在构造函数被多次调用时抛出异常。
public class Singleton {private static final Singleton instance = new Singleton();private static boolean instanceCreated = false;private Singleton() {if (instanceCreated) {throw new RuntimeException("单例实例已经存在,不能创建多个实例");}instanceCreated = true;}public static Singleton getInstance() {return instance;}
}
在上述代码中,instanceCreated 标志用于检测是否已经创建过实例。如果构造函数被再次调用,则抛出异常,防止通过反射创建新的实例。
使用枚举类型防止反射和序列化攻击
使用枚举类型实现单例模式是防止反射和序列化攻击的最简单和最有效的方法。枚举类型在 Java 中是天然的单例,并且防止反射攻击和序列化攻击。
public enum EnumSingleton {INSTANCE;public void someMethod() {// some method}
}
枚举类型的单例不仅简单,而且可以防止反射和序列化导致的单例破坏问题。
单例模式的实际应用案例
数据库连接池管理
数据库连接池是一个典型的单例模式应用场景。通过单例模式,确保整个应用程序只存在一个数据库连接池实例,从而有效管理数据库连接资源。
public class DatabaseConnectionPool {private static DatabaseConnectionPool instance;private ConnectionPool pool;private DatabaseConnectionPool() {// 初始化连接池}public static synchronized DatabaseConnectionPool getInstance() {if (instance == null) {instance = new DatabaseConnectionPool();}return instance;}public Connection getConnection() {return pool.getConnection();}
}
日志管理
日志管理也是单例模式的一个常见应用。通过单例模式,确保整个应用程序使用同一个日志记录器实例,从而统一管理日志输出。
public class Logger {private static Logger instance;private Logger() {// 初始化日志配置}public static synchronized Logger getInstance() {if (instance == null) {instance = new Logger();}return instance;}public void log(String message) {// 记录日志}
}
配置文件管理
配置文件管理通常也使用单例模式,确保整个应用程序只加载一次配置文件,并提供统一的接口访问配置数据。
public class ConfigurationManager {private static ConfigurationManager instance;private Properties properties;private ConfigurationManager() {// 加载配置文件properties = new Properties();try (InputStream input = new FileInputStream("config.properties")) {properties.load(input);} catch (IOException ex) {ex.printStackTrace();}}public static synchronized ConfigurationManager getInstance() {if (instance == null) {instance = new ConfigurationManager();}return instance;}public String getProperty(String key) {return properties.getProperty(key);}
}
总结
单例模式的最佳实践
- 私有构造函数:确保构造函数是私有的,防止外部直接实例化。
- 静态方法获取实例:通过静态方法获取唯一的实例。
- 防止反射攻击:在构造函数中添加检查,防止反射攻击。
- 防止序列化破坏:实现
readResolve方法,防止反序列化创建新的实例。 - 线程安全:在多线程环境中,使用合适的方式(如双重检查锁定、静态内部类、枚举单例)确保线程安全。
单例模式的使用建议
- 资源管理:适用于需要全局管理的资源,如数据库连接池、日志记录器、配置文件等。
- 性能考虑:在性能敏感的应用中,确保单例的创建和访问是高效的。
- 避免过度使用:虽然单例模式有其优势,但过度使用可能导致代码难以测试和维护。在设计时应慎重考虑是否真的需要单例模式。
- 测试友好:在单元测试中,可以使用依赖注入或其他设计模式来替代单例,以便于测试。
通过遵循这些最佳实践和使用建议,可以在项目中有效地应用单例模式,确保其稳定性和可维护性。
相关文章:
【设计模式】单例模式 在java中的应用
文章目录 引言什么是单例模式单例模式的应用场景单例模式的优缺点优点缺点 单例模式的基本实现饿汉式单例模式懒汉式单例模式双重检查锁定静态内部类枚举单例 单例模式的线程安全问题多线程环境下的单例模式线程安全的实现方式1. **懒汉式单例模式(线程不安全&#…...
burp suite 8
声明! 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下,如涉及侵权马上删除文章,笔记只是方便各位师傅的学习和探讨,文章所提到的网站以及内容,只做学习交流,其他均与本人以及泷羽sec团队无关&a…...
为什么在Java中super与this不能共存于子类构造器中,其中this起什么作用
在 Java 中,super 和 this 是两个关键字,它们在子类的构造器中有特定的用途和限制。 super 关键字: super 用于从父类(超类)访问成员(属性和方法)或者调用父类的构造方法。 在子类的构造器中&…...
Hypothesis:高效的 Python 测试工具
简介:Hypothesis 是一个强大的 Python 测试库,旨在自动生成各种测试案例,以帮助开发者发现潜在的边界问题和隐藏的错误。通过对输入数据进行智能化的探索,Hypothesis 能够为测试提供更全面的覆盖,避免遗漏一些极端或不…...
Terminus Calculator 计算原理分享
在《使命召唤:黑色行动 6》僵尸模式中,Terminus 关卡的研究办公室里有一个复杂的数学谜题需要解决。为了获得多相共振器,玩家需要计算出三个数字并输入电脑。虽然可以花费 5000 精华来获得答案,但使用 Terminus Calculator 可以更…...
Wwise 使用MIDI文件、采样音频
第一种:当采样音频只有一个文件的时候 1.拖入MIDI文件到Interactive Music Hierarchy层级 2.拖入采样音频到Actor-Mixer Hierarchy层级 3.勾选MIDI显示出面板,设置Root Note与采样音频音高相同,这里是C#5 4.播放测试,成功&…...
在CentOS上无Parallel时并发上传.wav文件的Shell脚本解决方案
在CentOS上无Parallel时并发上传.wav文件的Shell脚本解决方案 背景概述解决方案脚本实现脚本说明使用指南注意事项在CentOS操作系统环境中,若需并发上传特定目录下的.wav文件至HTTP服务器,而系统未安装GNU parallel工具,我们可通过其他方法实现此需求。本文将介绍一种利用Sh…...
【RocketMQ 源码分析(一)】设计理念与源码阅读技巧
RocketMQ 的设计理念与源码阅读技巧 一、设计理念二、源码设计三、源码阅读技巧 一直想仔细仔细看看这个 RocketMQ 的源码,学学它的设计思想和编码风格,没准在以后自己在设计和编码的时候有思考的方向。这是专栏的第一篇 —— 介绍下 RocketMQ 的一些设计…...
独立ip服务器有什么优点?
网站的性能和安全性直接影响到用户体验和业务发,独立IP服务器作为一种主流的托管方式,因其独特的优势而受到许多企业和个人站长的青睐。与共享IP相比,独立IP服务器到底有哪些优点呢? 使用独立IP的用户不必担心与其他网站共享同一…...
如何使用Python库连接Redis
1、redis-py 库封装一个 Redis 工具类可以帮助我们简化 Redis 的操作并提高代码的复用性和可维护性。 安装redis pip install redisimport redis import logginglogging.basicConfig(levellogging.INFO) logger logging.getLogger(__name__)class RedisUtils:def __init__(s…...
Vant UI +Golang(gin) 上传文件
前端基本用法:点击查看 实现代码: const afterRead (file) > {console.log(file);//set content-type to multipart/form-dataconst formData new FormData();formData.append("file", file.file);request.POST("/api/v1/users/up…...
【Unity高级】如何实现粒子系统的间歇式喷射
先看下要最终实现的效果: 代码如下: using UnityEngine; using System.Collections;public class ParticleBurstController : MonoBehaviour {private ParticleSystem _particleSystem; // 获取粒子系统public float burstDuration 2f; // 每次…...
通过linux命令获取自选股票价格及大盘涨跌幅
技术发展与数据获取需求 互联网与金融数据融合:随着互联网的普及和金融市场的数字化发展,金融数据的获取和分析变得更加便捷和重要。投资者希望能够及时、准确地获取股票价格和市场指数等信息,以便做出合理的投资决策。Linux 作为一种强大的操作系统,为数据获取和处理提供…...
透彻理解并解决Mockito模拟框架的单元测试无法运行的问题
本篇的实例基于Maven IDE (VS Code) 运行 在VS Code 运行的时候, 不需要在pom.xml 中添加任何插件就可以在测试类中看到如下的绿色按钮,单击就可以运行使用Mockito 注解 ExtendWith(MockitoExtension.class) 或是 Mockito 代码方式的测试。 不使用注…...
vue3字典数据的显示问题(使用hooks解决)
我们在使用 element-plus的时候,经常会使用一些字典数据, 在搜索框的时候,字典数数要使用 el-select el-option 来显示,当在table表格的时候,我们通常记录的是 字典数据的id , 又要把它改变成 字典数据的 name 属性 因…...
Elasticsearch 单节点安全配置与用户认证
Elasticsearch 单节点安全配置与用户认证 安全扫描时发现了一个高危漏洞:Elasticsearch 未授权访问 。在使用 Elasticsearch 构建搜索引擎或处理大规模数据时,需要启用基本的安全功能来防止未经授权的访问。本文将通过简单的配置步骤,为单节…...
二分查找(带图详解)
优选算法系列 文章目录 优选算法系列前言一、二分查找的思想二、算法使用小总结 三、代码实现四、二分查找拓展4.1、查找第一次出现的target小总结 4.2、target最后出现的位置小总结 五、代码总结 前言 在这篇博客中,我会给大家分享二分查找及其扩展。 这是链接-&…...
【Git】:标签管理
目录 理解标签 创建标签 操作标签 理解标签 标签的作用 标记版本:标签 tag ,可以简单的理解为是对某次 commit 的⼀个标识,相当于起了⼀个别名。例如,在项目发布某个版本的时候,针对最后⼀次 commit 起⼀个 v1.0 这样…...
物品识别 树莓派 5 YOLO v5 v8 v10 11 计算机视觉
0. 要实现的效果 让树莓派可以识别身边的一些物品,比如电脑,鼠标,键盘,杯子,行李箱,双肩包,床,椅子等 1. 硬件设备 树莓派 5 raspberrypi.com/products/raspberry-pi-5/树莓派官方摄…...
单片机软件工程师前景分析
单片机软件工程师的前景在2024年看起来是积极的。随着物联网(IoT)、自动化、智能设备等领域的快速发展,对于能够开发基于单片机(MCU)如STM32、ARM、51等嵌入式系统的软件工程师需求持续增长。这些工程师负责设计和实现…...
从静态分析到代码自愈:构建自动化自我审查工具提升代码质量
1. 项目概述:从“自我审视”到“代码自愈”的工程实践在软件开发的日常中,我们常常会陷入一种“当局者迷”的困境:自己写的代码,怎么看都觉得逻辑清晰、结构完美,但一旦交给同事评审或者上线运行,各种潜在的…...
米尔MYS-8MMX开发板实战:从交叉编译到网络视频监控系统搭建
1. 开箱与初体验:米尔MYS-8MMX开发板印象作为一名在嵌入式领域摸爬滚打多年的开发者,拿到一块新的开发板,那种感觉就像老木匠看到一块上好的木料,总想立刻上手试试它的“成色”。米尔电子这次推出的MYS-8MMX开发板,基于…...
如何高效配置阅读APP书源:完整指南助你轻松获取全网小说资源
如何高效配置阅读APP书源:完整指南助你轻松获取全网小说资源 【免费下载链接】Yuedu 📚「阅读」自用书源分享 项目地址: https://gitcode.com/gh_mirrors/yu/Yuedu 还在为找不到心仪的小说而烦恼吗?想要打造属于自己的个性化阅读环境吗…...
Mybatis-Plus条件构造器实战:QueryWrapper与UpdateWrapper的进阶应用与避坑指南
1. 为什么需要条件构造器? 在日常开发中,数据库操作是绕不开的话题。记得我刚入行时,每次写SQL都要手动拼接字符串,不仅容易出错,还经常被SQL注入漏洞困扰。后来接触到MyBatis,虽然解决了安全问题…...
8款投屏软件亲测对比:哪款才是真正的“良心之选”?
市面上的投屏软件多如牛毛,但真正好用的没几个。为了帮大家避坑,我亲自下载、安装、使用了8款常见的投屏工具,从是否收费、有无广告、功能丰富度、兼容性、实际体验五个维度做了深度测试。下面是我的真实使用感受,希望对你有帮助。…...
面向28nm ELK晶圆的WLCSP封装激光开槽质量与可靠性研究
2017 — Investigation of Production Quality and Reliability Risk of ELK Wafer WLCSP Package Research and Development, Taiwan Semiconductor Manufacturing Company, Ltd., Hsinchu Science Park, Hsinchu, Taiwan, R.O.C. 摘要 本文系统研究了28nm工艺ELK(极端低k)…...
AI Agents 越智能,企业的人类判断力需求反而会爆炸式增长:Jevons 悖论在企业落地中的隐形反弹
在企业全面拥抱 AI Agents 的当下,最容易被忽略的不是模型能力,而是“智能变便宜”之后带来的责任边界扩张。产品团队让 Agent 自动起草客户邮件、更新工单、标记流失风险、总结销售通话、推荐代码变更、升级支持问题、准备决策材料——每一步都变得前所…...
TSSP77038红外解调器:从原理到实战,打造高可靠接近传感与光束中断系统
1. 项目概述:从“遥控”到“感知”的红外新思路在嵌入式开发和电子制作领域,红外(IR)技术几乎是每个玩家都会接触到的老朋友。我们最熟悉的莫过于家里的电视、空调遥控器,它们通过发射一串调制在38KHz载波上的红外脉冲…...
从WCGW代码事故集看软件开发的常见陷阱与防御性编程实践
1. 项目概述:一个“看热闹不嫌事大”的代码仓库在程序员的世界里,除了正经八百的业务代码和开源框架,总有一些项目,它们诞生的初衷不是为了解决某个严肃的技术难题,而是为了捕捉、记录那些让人哭笑不得、甚至有点“幸灾…...
朋友学过都说好的家电清洗培训 行业前景与培训内容科普解读
家电清洗培训行业前景随着人们生活水平的提高,家电的普及率越来越高,对家电清洗的需求也日益增长。据相关数据显示,近年来家电清洗市场规模呈现逐年上升的趋势。在城市中,越来越多的家庭开始重视家电的清洁与保养,以延…...
