Java Reference类及其实现类深度解析:原理、源码与性能优化实践

1. 引言:Java引用机制的核心地位

在JVM内存管理体系中,Java的四种引用类型(强、软、弱、虚)构成了一个精巧的内存控制工具箱。它们不仅决定了对象的生命周期,还为缓存设计、资源释放和内存泄漏排查提供了基础设施支持。随着应用规模的扩大和内存敏感场景的增多,开发者对这些引用机制的掌握程度将直接影响系统的性能与稳定性。

从表面上看,SoftReference、WeakReference、PhantomReference不过是java.lang.ref.Reference的三个子类,但深入底层源码我们会发现:

  • 它们依赖JVM GC周期,将引用对象回收事件传递至Java层;

  • 引用状态通过pending链表和ReferenceHandler线程协同传递;

  • FinalReference与finalize()方法存在特殊耦合,承担资源清理关键角色。

本系列文章将带你逐步深入这些机制,通过理论与实战的结合,掌握Java引用的真正力量。

2. 核心概念:Reference类及其子类详解

强引用(Strong Reference)
Object obj = new Object(); // 强引用
obj = null; // 可被回收
  • 只要强引用存在,对象就不会被GC。

  • 最常见的引用方式,也是导致内存泄漏的主要原因之一。

软引用(SoftReference)
SoftReference<Object> softRef = new SoftReference<>(new Object());
System.out.println(softRef.get()); // 可能返回null
  • 当内存不足时,GC 会尝试回收软引用对象。

  • 常用于缓存系统,如图片缓存。

弱引用(WeakReference)
WeakReference<Object> weakRef = new WeakReference<>(new Object());
System.gc();
System.out.println(weakRef.get()); // 可能为null
  • GC时立即清除,即使内存充足也不保留。

  • 常用于Map结构中存放临时对象(如ThreadLocal Map)。

虚引用(PhantomReference)
ReferenceQueue<Object> queue = new ReferenceQueue<>();
PhantomReference<Object> phantomRef = new PhantomReference<>(new Object(), queue);
System.out.println(phantomRef.get()); // 永远返回null
  • 无法通过get访问对象,仅用于监控对象是否被回收。

  • 必须与ReferenceQueue配合使用。

ReferenceQueue的作用
  • 每当GC回收了某个被引用的对象,相应的Reference对象将被插入其关联的ReferenceQueue中。

  • 用户线程可以通过poll/remove方法监听并处理这些事件,执行资源清理等逻辑。

引用对象生命周期状态机

Java引用的状态可以用状态机方式建模:

  • 活跃态(Active):正常引用阶段,GC尚未回收目标对象。

  • Pending态:GC回收目标对象后,JVM将该Reference加入pending链表,待ReferenceHandler处理。

  • Enqueued态:ReferenceHandler线程将其加入ReferenceQueue,供用户线程轮询处理。

  • Inactive态:已经处理完毕,引用不再可用。

通过这种状态建模,我们可以精确控制资源生命周期,避免资源泄漏。

3. 基本使用:SoftReference、WeakReference、PhantomReference 实践

在掌握了四种引用类型的定义与生命周期后,我们需要通过具体代码实践来深入理解它们在真实场景中的应用方式。以下示例涵盖缓存设计、临时对象管理与资源释放三个方向,帮助开发者掌握如何在日常开发中使用引用类型。


3.1 SoftReference:实现内存敏感型缓存

软引用最常用于内存敏感的缓存场景,例如图片缓存、结果缓存等。

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;public class SoftCache<K, V> {private final Map<K, SoftReference<V>> cache = new HashMap<>();public void put(K key, V value) {cache.put(key, new SoftReference<>(value));}public V get(K key) {SoftReference<V> ref = cache.get(key);return ref != null ? ref.get() : null;}
}

运行说明:

  • 在内存充足时,缓存中的对象可多次复用。

  • 内存不足时,GC 会回收缓存项,节省堆空间。

适用场景:

  • 应用层图片缓存、配置缓存、预处理结果等。


3.2 WeakReference:避免临时对象导致内存泄漏

弱引用适用于保存临时对象,避免其阻止GC回收。

import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.Map;public class WeakMap<K, V> {private final Map<K, WeakReference<V>> map = new HashMap<>();public void put(K key, V value) {map.put(key, new WeakReference<>(value));}public V get(K key) {WeakReference<V> ref = map.get(key);return ref != null ? ref.get() : null;}
}

测试示例:

public class TestWeakMap {public static void main(String[] args) {WeakMap<String, byte[]> map = new WeakMap<>();map.put("big", new byte[10 * 1024 * 1024]); // 10MBSystem.gc();System.out.println("After GC: " + map.get("big"));}
}

输出:

After GC: null(可能,取决于GC是否发生)

适用场景:

  • ThreadLocal、ClassLoader缓存、临时对象缓存等。


3.3 PhantomReference:实现资源释放与对象终止回调

虚引用常用于在对象被GC后触发清理动作(如关闭文件句柄、释放本地资源)。必须配合ReferenceQueue使用。

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;public class ResourceCleaner {private static class LargeObject {private final byte[] data = new byte[5 * 1024 * 1024]; // 5MB@Overrideprotected void finalize() {System.out.println("Finalize called");}}public static void main(String[] args) throws InterruptedException {ReferenceQueue<LargeObject> queue = new ReferenceQueue<>();LargeObject obj = new LargeObject();PhantomReference<LargeObject> phantom = new PhantomReference<>(obj, queue);obj = null;System.gc();Reference<?> ref = queue.remove();if (ref == phantom) {System.out.println("Object is reclaimed. Clean up manually.");}}
}

运行说明:

  • 虚引用对象通过队列通知GC完成。

  • 可用于资源清理线程统一释放对象占用的本地资源。

适用场景:

  • DirectByteBuffer释放、数据库连接池、自定义对象池等。

4. 源码深度解析:Reference类的内部状态机与GC协作

Java引用的运行机制不仅仅体现在引用类型的语义差异上,更深入的实现在于 Reference 类的状态管理、与 GC 的交互机制、以及系统线程(如 ReferenceHandler、Finalizer、Cleaner)的协作逻辑。本章节将结合 Java 8 源码,详细解析其内部实现与状态机模型,帮助读者掌握其在 JVM 内存管理中的底层运作机制。


4.1 Reference的生命周期状态模型

每一个 Reference 对象在 GC 生命周期中大致经历如下几个阶段:

  1. Active(活跃):新建后正在使用。

  2. Discovered(被GC发现):GC发现其 referent 不再可达。

  3. Pending(等待入队):加入到 pending 链表,待 ReferenceHandler 入队。

  4. Enqueued(已入队):被 ReferenceHandler 放入其关联的 ReferenceQueue。

  5. Cleared(已清除):引用已不可用(referent 设为 null)。

这些阶段由 JVM 的 GC 线程和 Java 层的 ReferenceHandler、Cleaner 等共同推动。


4.2 Reference与GC的协作:注册与回调流程

在对象被 GC 判断为不可达时,JVM 不会直接处理引用类型,而是将其“发现”后加入专门的链表。引用对象必须事先注册到 JVM 内部的引用处理子系统中:

ReferenceQueue<Object> queue = new ReferenceQueue<>();
SoftReference<Object> ref = new SoftReference<>(new Object(), queue);

当 GC 确认该引用的 referent 不再强可达(Strongly Reachable),它会将该 Reference 加入内部“discovered”列表,并由 ReferenceProcessor 分派到 Reference.pending 静态链表:

Reference<Object> r = new SoftReference<>(obj, queue);
// 在 GC 时:r.referent = null;  -> r 进入 Reference.pending 链表

4.3 ReferenceHandler:负责 pending 入队处理

ReferenceHandler 是 JVM 启动时初始化的守护线程,负责轮询处理 Reference.pending 静态链表,将其入队到用户指定的 ReferenceQueue。

static class ReferenceHandler extends Thread {public void run() {while (true) {Reference<?> r;synchronized (lock) {if ((r = pending) != null) {pending = r.discovered;} else {try {lock.wait();} catch (InterruptedException x) {}continue;}}r.enqueue(); // 加入ReferenceQueue}}
}

关键点:

  • pending 是一个链表,由 GC 填充,ReferenceHandler 消费。

  • enqueue() 会将该引用加入其注册的 ReferenceQueue,供应用层查询。


4.4 Finalizer 与 FinalReference:对象终结处理

finalize() 方法是 Object 类提供的回调钩子,其触发机制依赖于 Finalizer 引用对象的特殊处理流程:

  • JVM 创建对象时,如果其类重写了 finalize() 方法,则 JVM 会在其构造之后注册一个 FinalReference 对象。

  • GC 判断其不可达后,不会立刻回收,而是将 FinalReference 加入 Finalizer 队列。

  • Finalizer 守护线程从该队列中取出对象,调用其 finalize() 方法。

// FinalizerThread 示例(java.lang.ref.Finalizer)
public void run() {for (;;) {Finalizer f = (Finalizer) queue.remove();f.runFinalizer();}
}

⚠️ 说明:Java 9 开始官方建议弃用 finalize(),转而使用 Cleaner 机制。


4.5 Cleaner:推荐的资源清理方式

java.lang.ref.Cleaner 是 Java 9 引入的资源清理机制(Java 8 可用内部实现),底层基于 PhantomReferenceReferenceQueue

public class CleanerExample {static class Resource implements Runnable {public void run() {System.out.println("[Cleaner] releasing resource...");}}public static void main(String[] args) {Object obj = new Object();Cleaner cleaner = Cleaner.create();cleaner.register(obj, new Resource());obj = null;System.gc();// Cleaner后台线程检测对象回收并触发run()}
}

优点:

  • 不依赖finalize(),更安全。

  • 自动配套后台线程处理清理逻辑。

  • 可避免对象复活、效率更高。


4.6 ReferenceQueue:引用入队与消费机制

每个 Reference 类型(除了强引用)在创建时都可指定一个 ReferenceQueue

ReferenceQueue<MyObject> queue = new ReferenceQueue<>();
SoftReference<MyObject> ref = new SoftReference<>(myObj, queue);

myObj 被 GC 回收后,ref 会被 ReferenceHandler 放入 queue

应用程序可轮询该队列,或阻塞等待引用对象入队:

Reference<? extends MyObject> polled = queue.poll(); // 非阻塞
Reference<? extends MyObject> removed = queue.remove(); // 阻塞

4.7 小结:GC协同机制带来的优势

Java 的 Reference 实现通过 GC 回调机制、pending 链表、守护线程(ReferenceHandler、Finalizer、Cleaner)实现了引用类型的高效分离与延迟处理:

  • GC 保持主导地位,引用处理是“回调友好”的异步模型。

  • 引用类型由系统统一管理,避免资源泄漏与手动清理复杂度。

  • Cleaner 机制为资源释放提供了更现代、线程安全的方案。

5. 引用滥用的隐患与优化实践

尽管 Java 提供了丰富的引用类型来增强内存控制能力,但在实践中,不当使用这些引用机制可能带来内存泄漏、回收延迟、性能下降等严重问题。本章将分析几种常见的引用滥用场景,并结合 GC 行为与应用实践提供优化建议。


5.1 软引用滥用:缓存泛滥与 OOM

问题描述: 软引用常用于缓存设计,但开发者容易将所有数据都放入 SoftReference 包裹的缓存容器,假设 JVM 会智能清理,实际却容易导致堆空间持续膨胀。

示例场景:

Map<String, SoftReference<byte[]>> cache = new HashMap<>();
for (int i = 0; i < 10000; i++) {cache.put("key" + i, new SoftReference<>(new byte[1_000_000])); // 每次1MB
}

潜在后果:

  • 如果没有立即触发 GC,缓存对象持续占用大量堆内存。

  • 容器本身(如 HashMap)强引用 key 和 SoftReference 对象,GC 无法清理缓存键值。

优化建议:

  • 限制缓存容量,采用 LRU/LFU 策略,避免无限增长。

  • 使用成熟缓存框架(如 Caffeine),它们内部合理结合引用、弱键与 eviction 策略。


5.2 弱引用滥用:ThreadLocal 内存泄漏

问题描述: ThreadLocal 使用 ThreadLocalMap 存储数据,其键为 WeakReference。但值若未被手动移除,会因线程强引用 ThreadLocalMap 而泄漏。

示例代码:

ThreadLocal<byte[]> local = new ThreadLocal<>();
local.set(new byte[10_000_000]);
// Thread未结束,但未调用 remove()

风险原因:

  • 键被 GC 回收后,值仍然存在于 Entry 中(ThreadLocalMap 中的 value),泄漏直至线程退出。

优化建议:

  • 始终在使用完 ThreadLocal 后调用 remove()

try {local.set(data);// use data
} finally {local.remove();
}
  • 避免在线程池中长期持有大对象。


5.3 虚引用误用:未监控 ReferenceQueue

问题描述: PhantomReference 必须配合 ReferenceQueue 使用,才能实现资源回收回调。但很多开发者只创建 PhantomReference 而未正确轮询其队列,导致资源清理线程无法触发。

常见误区:

PhantomReference<Object> ref = new PhantomReference<>(obj, null); // 无队列!

后果:

  • 无法检测对象被 GC 回收的时机。

  • 与 Cleaner 搭配失败,清理逻辑永远不触发。

优化建议:

  • 使用 Cleaner 替代手动 PhantomReference 管理。

  • 若使用 PhantomReference,务必独立线程轮询 ReferenceQueue:

while ((ref = queue.remove()) != null) {cleanup();
}

5.4 Finalizer 滥用:对象复活与回收延迟

问题描述: 重写 finalize() 方法可能导致对象复活(即在 finalize() 中将 this 赋给静态变量),从而使对象逃脱 GC。

代码示例:

@Override
protected void finalize() throws Throwable {FinalizerLeak.rescue = this; // 对象复活
}

问题后果:

  • 增加 GC 负担,回收延迟严重。

  • Finalizer 线程阻塞会导致整个清理队列堆积。

优化建议:

  • Java 9+ 推荐弃用 finalize,采用 Cleaner。

  • 不再依赖 finalize 进行重要资源释放。


5.5 Cleaner 滥用:引用泄漏与资源未释放

问题描述: Cleaner 的注册机制依赖 PhantomReference 包装目标对象,若引用未失效或 Resource 逻辑失误,则不会触发资源释放。

隐蔽风险:

  • 注册的清理任务无异常保护,run() 抛错将终止后续逻辑。

  • Cleaner 所引用对象链条复杂时,GC 无法回收。

优化建议:

  • 保证 Cleaner 的目标对象不再有强引用。

  • Runnablerun() 方法必须捕获所有异常,避免影响清理线程。

cleaner.register(obj, () -> {try {close();} catch (Exception e) {log.warn("clean failed", e);}
});

5.6 总结:安全使用引用类型的六大原则

  1. 软引用不可替代缓存策略,限制缓存大小是必要的。

  2. ThreadLocal 用完即清,避免在线程池环境中遗留大对象。

  3. PhantomReference 必须搭配 ReferenceQueue,否则失去意义。

  4. 不依赖 finalize 释放资源,应使用 Cleaner 替代。

  5. 注册 Cleaner 时,确保目标对象无强引用

  6. 所有清理逻辑应具备异常保护机制

6. 性能调优建议:缓存设计与内存敏感场景优化

Reference 引用机制带来了强大的内存管理能力,但其使用方式对性能和稳定性有直接影响。本章节将从缓存设计、GC行为、对象生命周期控制、线程协作等多个角度,提供基于实践的调优策略,帮助读者在性能与内存控制间取得平衡。


6.1 缓存设计优化:SoftReference 与 WeakReference 的边界

✅ 合理使用 SoftReference 缓存

SoftReference 最适合用在“低优先级但可复用”的对象缓存上,例如图片缓存、编译器缓存等。

问题:很多系统错误地使用 SoftReference 替代 LRU 缓存,导致缓存命中率低,频繁GC后缓存清空。

优化建议

  • SoftReference 缓存需辅以显式清理机制(如定期清空不可达项、结合 ReferenceQueue)。

  • 设置最大容量,避免无边界增长。

  • 配合内存告警机制,动态调整缓存策略。

示例改进版 SoftCache:

public class SoftCache<K, V> {private final Map<K, SoftReference<V>> cache = new ConcurrentHashMap<>();private final ReferenceQueue<V> queue = new ReferenceQueue<>();public void put(K key, V value) {processQueue();cache.put(key, new SoftReference<>(value, queue));}public V get(K key) {SoftReference<V> ref = cache.get(key);return ref != null ? ref.get() : null;}private void processQueue() {Reference<? extends V> ref;while ((ref = queue.poll()) != null) {cache.values().remove(ref);}}
}

⚠️ 避免弱引用构建核心缓存

WeakReference 在下一次 GC 后几乎必然被清除,适用于对象的生命周期极短的情况。

错误用法:使用 WeakReference 作为 LRU 缓存核心容器,结果每次访问都 miss。

替代方案

  • 对于真正的 LRU 缓存,优先使用 LinkedHashMapCaffeine 等成熟方案。

  • 如果使用 WeakHashMap,仅适用于 key 生命周期需跟随 value 的场景。


6.2 内存敏感场景:PhantomReference 与资源回收

PhantomReference 主要用于资源回收场景,如 direct buffer 清理、IO资源释放。

性能提示

  • 不建议用于业务层逻辑流程控制。

  • 清理线程需异步处理,不应阻塞主流程。

  • 可以用 Cleaner 或构造专门的清理线程。

示例:异步监听资源回收

public class PhantomCleaner {static class ResourceCleaner implements Runnable {public void run() {System.out.println("[清理线程] 释放资源...");}}public static void main(String[] args) throws Exception {Object resource = new Object();ReferenceQueue<Object> queue = new ReferenceQueue<>();PhantomReference<Object> ref = new PhantomReference<>(resource, queue);resource = null;System.gc();new Thread(() -> {try {Reference<?> removed = queue.remove();if (removed == ref) {new ResourceCleaner().run();}} catch (InterruptedException e) {Thread.currentThread().interrupt();}}).start();}
}

6.3 Cleaner与资源敏感型服务

Cleaner 是 JDK 推荐用于替代 finalize() 的清理工具,其本质使用 PhantomReference 实现。

性能注意事项

  • Cleaner 注册动作应当受控,避免对大量小对象反复注册。

  • 注册清理逻辑应避免抛出异常,以免影响 CleanerThread 运行。

  • 对于数据库连接、NIO 通道、MappedByteBuffer,推荐封装资源注册类。

示例:带限流注册机制的 Cleaner 管理器

public class SafeCleanerRegistry {private static final Cleaner cleaner = Cleaner.create();private static final AtomicInteger counter = new AtomicInteger();private static final int MAX_CLEANABLE = 1000;public static void register(Object obj, Runnable action) {if (counter.incrementAndGet() < MAX_CLEANABLE) {cleaner.register(obj, () -> {try {action.run();} catch (Throwable t) {System.err.println("[Cleaner] 清理失败: " + t);} finally {counter.decrementAndGet();}});} else {System.out.println("[Cleaner] 注册数量超限,跳过注册");}}
}

6.4 引用队列的异步处理策略

ReferenceQueue 入队是 GC 与用户线程之间的桥梁。为了避免阻塞或内存堆积,推荐专门使用后台线程消费该队列。

通用异步引用队列消费器模板:

public class ReferenceQueueWorker<T> implements Runnable {private final ReferenceQueue<T> queue;public ReferenceQueueWorker(ReferenceQueue<T> queue) {this.queue = queue;}public void run() {try {while (true) {Reference<? extends T> ref = queue.remove(); // 阻塞直到入队// 处理逻辑,如资源回收、日志、状态标记等System.out.println("[引用入队] " + ref);}} catch (InterruptedException e) {Thread.currentThread().interrupt();}}
}

在服务启动时调用:

ReferenceQueue<Object> queue = new ReferenceQueue<>();
Thread worker = new Thread(new ReferenceQueueWorker<>(queue));
worker.setDaemon(true);
worker.start();

6.5 总结:内存控制的平衡术

  • 不同引用类型应当明确边界,不宜混用。

  • ReferenceQueue 是连接 GC 和业务清理的桥梁,需主动处理。

  • Cleaner 是安全清理的推荐实践,但需谨慎使用。

  • 缓存优化不止依赖引用机制,更需要算法设计配合(如 LRU、定时失效)。

通过精细设计引用策略与资源清理机制,Java 应用能在 GC 友好与资源高效释放之间达到理想平衡。

7. 引用类型使用对比与性能评估

Java 提供的四种引用类型(Strong、Soft、Weak、Phantom)各有特点,适用于不同的应用场景。本章节从内存占用、GC 行为、清理延迟、性能开销四个维度进行横向对比,并通过典型场景说明其最佳实践和注意事项。


7.1 四种引用的对比表格

类型可达性级别GC回收时机是否可访问对象是否入队典型用途
StrongReference永不自动回收普通对象引用
SoftReference次强内存不足时回收缓存、内存敏感加载
WeakReference下一次 GC 即可能回收元数据、注册表、监听器
PhantomReference最弱GC 确定对象不可达之后否(get()=null)Cleaner、资源释放监控

注:Soft/Weak/Phantom 均可与 ReferenceQueue 配合,实现入队通知。


7.2 性能评估维度分析

维度SoftReferenceWeakReferencePhantomReference
GC参与频率中(内存敏感触发)高(每次GC都处理)高(每次GC都判定)
存活时间取决于内存使用状态很短最短(无法访问对象)
可访问性可访问 referent可访问 referent无法访问 referent
清理延迟可能延迟多次 GC一次 GC 后确定 GC 后执行
系统开销中(需要入队监控)低-中中-高(配清理线程)

7.3 典型使用场景建议

✅ SoftReference:用于内存敏感缓存
  • 图片/文本缓存

  • 大型对象短期复用

  • 避免 OOM 但保持命中率

⚠️ 建议:搭配最大容量策略 + ReferenceQueue 清理

✅ WeakReference:管理非关键资源
  • 元数据缓存(ClassLoader)

  • 听众注册表 / 观察者模式(避免泄漏)

  • 避免循环引用

⚠️ 建议:避免依赖 weak 缓存做 LRU 等持久性设计

✅ PhantomReference:系统资源释放/监控
  • DirectByteBuffer、MappedByteBuffer 清理

  • 自定义 native 资源释放

  • 与 Cleaner 协作使用

⚠️ 建议:由专用线程监听 ReferenceQueue,异步处理释放逻辑


7.4 性能陷阱与误区

  1. 错误缓存设计:使用 WeakReference 作为 LRU 缓存核心,几乎无法命中。

  2. 未处理 ReferenceQueue:Soft/Weak 入队后未消费,导致对象滞留。

  3. 过度注册 Cleaner:频繁对小对象调用 Cleaner.register(),造成后台线程压力。

  4. 使用 PhantomReference 做逻辑流程判断:由于 get() 始终返回 null,无法获取任何对象信息。


7.5 总结:选择策略与实践建议

  • 缓存设计:SoftReference + 显式清理策略

  • 短生命周期对象:WeakReference + Map/Set 管理

  • 资源清理/内存回调:Cleaner / PhantomReference + 异步处理线程

  • 引用队列处理:ReferenceQueue 必须主动消费,否则清理链路断裂

四类引用类型各自承担不同职责,合理搭配使用能最大化 JVM 的 GC 协作能力,实现高性能与内存安全的统一。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/90683.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/90683.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为云对碳管理系统的全生命周期数据处理流程

碳管理系统的全生命周期数据处理流程包含完整的数据采集、处理、治理、分析和应用的流程架构,可以理解为是一个核心是围绕数据的“采集-传输-处理-存储-治理-分析-应用”链路展开。以下是对每个阶段的解释,以及它们与数据模型、算法等的关系: 1. 设备接入(IoTDA) 功能: …

大模型安全风险与防护产品综述 —— 以 Otter LLM Guard 为例

大模型安全风险与防护产品综述 —— 以 Otter LLM Guard 为例 一、背景与安全风险 近年来&#xff0c;随着大规模预训练语言模型&#xff08;LLM&#xff09;的广泛应用&#xff0c;人工智能已成为推动文档处理、代码辅助、内容审核等多领域创新的重要技术。然而&#xff0c;…

1.2.2 计算机网络分层结构(下)

继续来看计算机网络的分层结构&#xff0c;在之前的学习中&#xff0c;我们介绍了计算机网络的分层结构&#xff0c;以及各层之间的关系。我们把工作在某一层的软件和硬件模块称为这一层的实体&#xff0c;为了完成这一层的某些功能&#xff0c;同一层的实体和实体之间需要遵循…

实训八——路由器与交换机与网线

补充——基本功能路由器&#xff1a;用于不同逻辑网段通信的交换机&#xff1a;用于相同逻辑网段通信的1.网段逻辑网段&#xff08;IP地址网段&#xff09;&#xff1a;IP地址的前三组数字代表不同的逻辑网段&#xff08;有限条件下&#xff09;&#xff1b;IP地址的后一组数字…

C++——构造函数的补充:初始化列表

C中&#xff0c;构造函数为成员变量赋值的方法有两种&#xff1a;构造函数体赋值和初始化列表。构造函数体赋值是在构造函数里面为成员变量赋值&#xff0c;如&#xff1a;class Data { public://构造函数体赋值Data(int year,int month,int day){_year year;_month month;_d…

代码随想录|图论|12岛屿周长

leetcode:106. 岛屿的周长 题目 题目描述 给定一个由 1&#xff08;陆地&#xff09;和 0&#xff08;水&#xff09;组成的矩阵&#xff0c;岛屿是被水包围&#xff0c;并且通过水平方向或垂直方向上相邻的陆地连接而成的。 你可以假设矩阵外均被水包围。在矩阵中恰好拥有…

开发制作模仿参考抄别人的小程序系统

很多老板看见别人公司的小程序系统界面好看&#xff0c;功能强大&#xff0c;使用人数多。就想要抄袭模仿参考别人家的小程序系统。想要了解一下有没有侵权风险&#xff0c;以及怎么开发制作开发制作模仿参考抄别人的小程序系统。首先回答第一个问题&#xff0c;只要你的小程序…

c语言中的数组IV

数组的集成初始化 集成初始化的定位 数组的大小 数组的赋值 不能直接将一个数组a赋值给数组b&#xff0c;只能通过遍历来实现 遍历数组 示例——检索元素在数组中的位置#include <stdio.h> int search(int key,int a[],int length); int main(void){int a[] {2,4,6,7,1,…

LDO选型

目录 一、最大输出电流 二、最大输入电压 三、最大功率&#xff1a;Pmax 四、负载动态调整率 五、输入电源纹波抑制比&#xff1a;PSRR 一、最大输出电流 参考TI LM1117IMPX-3.3/NOPB数据手册 由于LDO转换效率很低&#xff0c;LDO的标称最大电流 ≥ 实际最大负载电流 1…

飞算JavaAI:重构Java开发的“人机协同”新范式

目录一、从需求到架构&#xff1a;AI深度参与开发“顶层设计”1.1 需求结构化&#xff1a;自然语言到技术要素的准确转换1.2 架构方案生成&#xff1a;基于最佳实践的动态匹配二、编码全流程&#xff1a;从“手写代码”到“人机协同创作”2.1 复杂业务逻辑生成&#xff1a;以“…

解决SQL Server SQL语句性能问题(9)——SQL语句改写(7)

9.4.15. 消除join场景一 与Oracle等其他关系库类似,SQL Server中,join作为基本语法用于SQL语句中相关表之间的连接,有些场景中,join既可以增强SQL语句的可读性,同时,又可以提升SQL语句的性能,但有些场景中,join会导致CBO为SQL语句产生次优的查询计划,进而出现SQL语句…

深度学习-数据准备

一、数据准备 1.1定义 数据准备&#xff08;Data Preparation&#xff09; 是数据分析与机器学习流程中的核心环节&#xff0c;指将原始数据转换为适合分析或建模的结构化格式的过程。 1.2组成 数据准备主要由两个部分组成&#xff0c;一个是划分数据集&#xff0c;一个是构建…

IPA软件源预览系统源码(源码下载)

这是一款IPA软件源预览系统源码&#xff0c;搭建这个源码一定记住没有软件源的别搭建&#xff0c;因为你玩不明白&#xff0c;不是做IPA软件源的不要下载这套源码&#xff0c;简单的测试了&#xff0c;UI很舒服&#xff0c;喜欢的自行部署&#xff01; 源码下载&#xff1a;htt…

python 数据分析 单细胞测序数据分析 相关的图表,常见于肿瘤免疫微环境、细胞亚群功能研究 ,各图表类型及逻辑关系如下

这是一组 单细胞测序数据分析 相关的图表&#xff0c;常见于肿瘤免疫微环境、细胞亚群功能研究 &#xff0c;各图表类型及逻辑关系如下&#xff1a;使用kimi doubao 和deepseek &#xff0c;分析图标和pdf 豆包最好&#xff0c;用豆包分析| 图表类型 A、E&#xff08;堆叠柱状…

表达式索引海外云持久化实践:关键技术解析与性能优化

随着全球数字化转型加速&#xff0c;表达式索引技术正成为海外云服务商提升数据库性能的核心方案。本文将深度解析如何通过云原生架构实现索引持久化&#xff0c;对比主流云平台的技术实现差异&#xff0c;并给出跨国业务场景下的优化建议。 表达式索引海外云持久化实践&#x…

sprinboot团队任务管理系统 计算机毕业设计源码32322

摘 要 随着团队协作模式的日益多样化&#xff0c;传统的任务管理方法已无法满足现代团队对高效协作和任务分配的需求。因此&#xff0c;本研究通过引入信息化设计并实现了一套团队任务管理系统&#xff0c;旨在为管理员、成员用户和团长用户等用户提供高效、灵活的任务管理…

单链表,咕咕咕

1.引入单链表顺序表对于中间或者头部的删除&#xff0c;时间复杂度为O(N)&#xff0c;增容需要申请新的空间&#xff0c;拷贝数据&#xff0c;释放就空间&#xff0c;消耗。增容一般是2倍的增长&#xff0c;会有空间的浪费。为了解决这些问题&#xff0c;引入了单链表。2.单链表…

docker设置镜像加速

配置镜像加速器解决 Docker 拉取问题 在使用 Docker 拉取镜像时&#xff0c;我首先按照官方指引尝试配置阿里云镜像加速器。然而&#xff0c;多次操作后仍无法正常使用&#xff0c;怀疑是个人账号没有权限拉取镜像&#xff0c;但经过多轮权限检查与配置核对&#xff0c;始终未…

【计算机网络】王道考研笔记整理(2)物理层

第二章 物理层2.1 通信基础的基本概念本节主要介绍通信中常用的一些基本概念&#xff0c;包括&#xff1a;信源、信宿、信号、信道&#xff0c;以及码元、速率、波特。首先&#xff0c;我们来看什么是信源、信宿、信号、信道&#xff0c;这些概念通过一张图就可以理解。其中&a…

2023年IEEE TITS SCI2区TOP,增强回溯搜索算法EBSA+多无人机辅助商业包裹递送系统飞行规划,深度解析+性能实测

目录1.摘要2.回溯搜索算法BSA原理3.模型定义4.增强回溯搜索算法EBSA5.结果展示6.参考文献7.算法辅导应用定制读者交流1.摘要 利用无人机进行商业包裹投递可以显著推动物流行业的转型升级&#xff0c;这得益于节省了人力资源成本&#xff0c;而无人机正在成为智能交通运输系统的…