性能优化 - 案例篇:大对象的优化

article/2025/6/22 13:14:57

文章目录

  • Pre
  • 1. 引言
  • 2. String 的 substring 方法内存泄漏案例
    • 2.1 JDK6 的实现与内存泄漏
    • 2.2 JDK7+ 的修复
    • 2.3 优化启示
  • 3. 集合扩容的隐形成本
    • 3.1 StringBuilder 扩容机制
    • 3.2 ArrayList 扩容机制
    • 3.3 HashMap 扩容机制
    • 3.4 优化建议
  • 4. 结构维度:优化大对象的粒度与存储方式
    • 4.1 合理划分业务数据粒度
    • 4.2 使用 Bitmap 压缩布尔值
      • 4.2.1 Java 本地 `BitSet`
      • 4.2.2 Redis Bitmap
    • 4.3 布隆过滤器(Bloom Filter)原理
  • 5. 时间维度:冷热分离
    • 5.1 冷热分离常见方案
      • 5.1.1 数据双写(同步双写)
      • 5.1.2 写入 MQ 分发(异步双写)
      • 5.1.3 Binlog 同步(CDC)
    • 5.2 三种方案的对比与选型
  • 6. 思维发散:结果缓存池与其他复用技术
    • 6.1 数据库索引(B+ 树)
    • 6.2 序列化协议:JSON vs Protobuf
      • 6.2.1 性能比较
  • 7. 小结

在这里插入图片描述


Pre

性能优化 - 理论篇:常见指标及切入点

性能优化 - 理论篇:性能优化的七类技术手段

性能优化 - 理论篇:CPU、内存、I/O诊断手段

性能优化 - 工具篇:常用的性能测试工具

性能优化 - 工具篇:基准测试 JMH

性能优化 - 案例篇:缓冲区

性能优化 - 案例篇:缓存

性能优化 - 案例篇:数据一致性

性能优化 - 案例篇:池化对象_Commons Pool 2.0通用对象池框架


  1. 引言:说明“大对象”对性能的影响与优化动机;
  2. String substring 漏洞案例:回顾 JDK6 与 JDK7+ 的差异及注意事项;
  3. 集合扩容开销:展示常见集合(StringBuilder、ArrayList、HashMap)的扩容机制及潜在性能损耗;
  4. 对大对象的结构化优化:
    4.1 合理设计数据粒度——以用户信息为例,用 Hash 取代 JSON;
    4.2 Bitmap 压缩布尔数据——介绍 BitSet 与 Redis Bitmap 用法;
    4.3 布隆过滤器原理:减少内存占用、避免缓存穿透;
  5. 对大对象的时间维度优化:冷热分离三种常见方案(双写、MQ 同步、Binlog 同步);
  6. 结果缓存池思维发散:索引(B+ 树)、序列化(JSON vs Protobuf)示例;
  7. 小结:回顾上述优化策略与适用场景;

1. 引言

“大对象”是一个泛化概念,可以指:

  • 堆内大对象(例如,几 MB 的 String、长列表、复杂的 JSON 对象);
  • 网络传输大对象(如多媒体文件、长 JSON 串);
  • 数据库中的大数据行(包含大量列或大文本字段)。

之所以要对大对象进行优化,主要基于三点考量:

  1. 占用资源多:GC 需要更多时间来标记和整理大对象,若堆中存在大量短期大对象,可能导致频繁的 Full GC;
  2. 传输成本高:大对象跨网络传输时,占用带宽、增加 I/O 等待,延迟显著;
  3. 解析耗时:对大对象进行序列化、反序列化或部分解析时,需要更多 CPU 周期。

因此,在保证功能正确性的前提下,让“大对象变小”或“避免不必要的大对象操作”就成为了提高性能的重要手段。


2. String 的 substring 方法内存泄漏案例

Java 中 String 是不可变对象,当我们需要截取子串时,最常用的方法就是 substring(int beginIndex, int endIndex)

2.1 JDK6 的实现与内存泄漏

在这里插入图片描述

JDK6 时代,String 底层维护了一个 char[] value 数组,substring() 并不会复制需要的字符,而是通过:

public String substring(int begin, int end) {// 直接引用原来的字符数组,并保存 offset 和 countreturn new String(value, begin, end - begin);
}

这样会导致:

  • 原始 String 占有较大 char[],其引用一直存在于子串中;
  • 即使只保留子串,整个大数组也无法被 GC 回收,造成“内存泄漏”。

举例:

String content = dao.getLargeArticle(id); // content 长达数 MB
String summary = content.substring(0, 100);
articles.put(id, summary); // 仅保留 summary,但 large array 仍被引用

由于 summaryvalue 成员仍指向 content.value,JVM 无法回收那整个几 MB 的字符数组,导致堆内存持续膨胀。

2.2 JDK7+ 的修复

JDK7.0u6 开始,String 在截取时会复制所需字符片段:

public String substring(int beginIndex, int endIndex) {char[] newValue = Arrays.copyOfRange(value, beginIndex, endIndex);return new String(newValue);
}
  • 这样 summary 内部的新 char[] 只有 100 个字符大小,消除了对原大数组的引用;
  • 原始的 content 数组只要不被任何变量引用,便可被 GC 回收。

2.3 优化启示

  • 注意 JDK 版本差异:当我们在老项目中使用 substring() 或其他大对象“分片”操作,要先确认运行时 JDK 版本;
  • 手动拷贝:若不确定 String 底层是否复制,或者要兼容多版本,可显式 new String(content.substring(...)) 强制拷贝一次;
  • 及时切断引用:如果只需要保留子串,建议将原始大 String 置为 null 或尽快脱离作用域,帮助 GC 回收。

3. 集合扩容的隐形成本

Java 常用集合(如 StringBuilderArrayListHashMap)都采用“动态扩容”的策略,随着元素不断增加,底层数组会不断翻倍或按系数扩展。虽然这保证了“无上限”的灵活性,但也带来性能开销:

3.1 StringBuilder 扩容机制

源码片段(JDK8+):

void ensureCapacityInternal(int minCapacity) {// 默认容量为 16,第一次 expandCapacity 时会被替换int newCapacity = (value.length << 1) + 2;if (newCapacity - minCapacity < 0)newCapacity = minCapacity;value = Arrays.copyOf(value, newCapacity);
}
  • 每次扩容时按 “当前长度 × 2 + 2” 计算新容量;
  • Arrays.copyOf 会分配一个新的 char[] 并复制原数据,CPU 与内存带宽开销显著;

3.2 ArrayList 扩容机制

源码片段:

private void grow(int minCapacity) {int oldCapacity = elementData.length;// 扩容到 1.5 倍int newCapacity = oldCapacity + (oldCapacity >> 1);if (newCapacity - minCapacity < 0)newCapacity = minCapacity;elementData = Arrays.copyOf(elementData, newCapacity);
}
  • 扩容系数固定为 1.5(或 3/2),在渐进的元素添加场景下减少扩容次数;
  • 但同样会经历“新数组分配 + 原数据复制”,尤其是数据量上万时,复制开销非常明显;

3.3 HashMap 扩容机制

源码片段(简化自 JDK8):

void resize() {int oldCap = table.length;int newCap = oldCap << 1; // 总是翻倍Node<K,V>[] newTable = (Node<K,V>[]) new Node[newCap];// 重新散列:遍历所有旧桶,将节点链移到新桶for (Node<K,V> e : table)while (e != null) {Node<K,V> next = e.next;int idx = indexFor(e.hash, newCap);e.next = newTable[idx];newTable[idx] = e;e = next;}table = newTable;threshold = newCap * loadFactor;
}
  • 除了新数组分配,还需要 “逐节点重新散列”,会对每个 entry 重新计算 (hash & (newCap - 1)) 并链接到新桶,CPU 开销更大;
  • 扩容时无锁的情况下,若并发访问,可能导致竞争或元素丢失;若加锁则会阻塞其他线程。

3.4 优化建议

  1. 预估容量:若能提前知道大致元素数量,尽量 new ArrayList<>(expectedSize)new HashMap<>(expectedSize),避免扩容;

    // 例如需要存储1000个元素,loadFactor=0.75
    int initialCapacity = (int) (1000 / 0.75f) + 1; 
    List<String> list = new ArrayList<>(initialCapacity);
    
  2. Sparse vs Dense 场景选择合适集合:若元素稀疏且索引较大,可考虑 LinkedHashMapSparseArray(Android)等替代方案;

  3. 批量操作合并:若需要一次插入大量元素,尽量 addAll(Collection)putAll(Map),避免多次触发扩容。


4. 结构维度:优化大对象的粒度与存储方式

4.1 合理划分业务数据粒度

以用户基本信息为例:

  • 原始设计:

    # Redis 中以 String 方式存储 JSON
    key: user_{userId}
    value: {"id":1001,"name":"Alice","age":30,"sex":"female","email":"a@x.com", ...}
    
    • 缺点:每次只需“性别(sex)”时,都要 GET user_1001 → 得到完整 JSON 再在应用端解析;
    • 更新单个字段 sex 时,也需要先拿到整串 JSON,修改后再 SET user_1001,I/O 与带宽开销高;
  • 优化方案:使用 Redis Hash 存储

    # 主键不变,value 变为 Hash 结构
    key: user_{userId}
    fields: { "id":1001, "name":"Alice", "age":"30", "sex":"female", "email":"a@x.com", ... }
    
    • 读取单个字段:HGET user_1001 sex → 只返回 "female"
    • 更新单个字段:HSET user_1001 sex male → 只修改 Hash 槽而不改动其他字段;
    • 节省了 JSON 序列化/反序列化和完整字符串传输的开销。

4.2 使用 Bitmap 压缩布尔值

假设系统频繁需要存取用户“小规模 Boolean 属性”(如性别、签到状态、活跃状态等),全量存成 String 或 Hash 都显得太浪费。可以考虑:

4.2.1 Java 本地 BitSet

// 创建可存储 10 亿位的 BitSet,占用约 10e9 / 8 ≈ 125MB
static BitSet missSet = new BitSet(1_000_000_000);
static BitSet sexSet = new BitSet(1_000_000_000);// 示例:按需加载用户性别
String getSex(int userId) {if (!missSet.get(userId)) { // 首次访问String actualSex = dao.getSex(userId); // 从数据库查询missSet.set(userId, true);             // 标记已加载if ("female".equals(actualSex)) {sexSet.set(userId, true);} else {sexSet.set(userId, false);}}return sexSet.get(userId) ? "female" : "male";
}
  • 优势:一个 BitSet 内部用 long[] 存储,最小单位 64 位;10 亿位只需 10e9/64 ≈ 1.56e7long1.56e7 × 8B ≈ 125MB
  • 缺点:全部保存在 JVM 堆中仍然占用大量内存;若机器内存不足,应考虑将这类稀疏布尔映射存到 Redis Bitmap。

4.2.2 Redis Bitmap

// 设定 Redis key: user:sex_bitmap
// 用户性别:0 表示 male,1 表示 female// 在 Redis 中标记 userId 的性别
redisTemplate.opsForValue().setBit("user:sex_bitmap", userId, trueOrFalse);// 获取 userId 性别
boolean isFemale = redisTemplate.opsForValue().getBit("user:sex_bitmap", userId);
  • 存储压缩:Bitmap 在 Redis 中以紧凑二进制存储,不受稀疏索引过大影响;
  • 缺点:一次只能存一个布尔数组,若还要记录“是否签到”、“是否在线”等其他布尔值,需要多个 Bitmap key;

4.3 布隆过滤器(Bloom Filter)原理

当集合中存在 N 个元素,需要判断新元素是否在集合中时,直接遍历或使用 HashSet 可能占用大量内存或遍历时间。布隆过滤器能在“可接受的误判概率”范围内大幅降低内存占用:

  • 结构:使用一个长度为 M 的 Bitmap + k 个哈希函数;
  • 插入:对某元素计算 k 个哈希,分别对应的 Bitmap 位设为 1;
  • 查询:对某元素计算 k 个哈希,如果出现任何一位为 0,则该元素一定不在集合;如果所有位都为 1,则该元素“可能在集合”——存在“误判”概率;
  • 内存效率:若想存储 1 亿个元素,控制误判率在 1%,所需内存约数百 MB ;

应用示例:缓存穿透防御

// 初始化布隆过滤器,预计插入数据量 n=1e7,误判率 p=0.01
BloomFilter<String> bloom = BloomFilter.create(Funnels.stringFunnel(Charset.defaultCharset()), 10_000_000, 0.01);// 将所有合法用户ID 放入布隆过滤器
for (String userId : userIdListFromDB) {bloom.put(userId);
}// 访问时先查询布隆
if (!bloom.mightContain(requestedUserId)) {// 直接返回 404 或提示“用户不存在”,避免落库
} else {// 再走缓存/数据库查询
}
  • 优点:内存占用远低于 HashSetTreeSet,仅有“一定概率误判存在、绝不会漏判不存在”;
  • 缺点:误判率不可避免,若误判导致“真正不存在”却被判为存在,需要后续缓存或 DB 依旧做二次校验。

5. 时间维度:冷热分离

除了从“结构纬度”(切分或压缩大对象)来优化,“时间纬度”上的冷热分离也是常见手段,将“热数据”保持在高性能存储,“冷数据”迁移到低成本存储:

5.1 冷热分离常见方案

5.1.1 数据双写(同步双写)

  • 思路:在同一业务事务中同时写入“热库”(如 MySQL)和“冷库”(如 HBase、Elasticsearch);
  • 优点:同步完成,两边数据可保持一致;
  • 缺点:需要“分布式事务”保障原子性,技术实现代价大;遗留系统代码分散、业务逻辑复杂时,很难统一改造。

5.1.2 写入 MQ 分发(异步双写)

  • 思路:业务写操作 → 发消息到 MQ(如 Kafka、RocketMQ) → 多个消费者订阅消息,分别写入热库与冷库;
  • 优点:业务与双写解耦,消费者各自独立,可并行/批量处理;
  • 缺点:引入 MQ 增加系统复杂度;消息顺序、消息丢失、重复消费需额外处理;

5.1.3 Binlog 同步(CDC)

  • 思路:利用 MySQL 的 Binlog,借助 Canal、Maxwell 等组件实时解析 Binlog → 将写操作同步到冷库或搜索引擎;
  • 优点:无需在业务代码层插入双写逻辑,靠数据库自身日志机制;延迟通常在毫秒级别;
  • 缺点:只能对关系型数据库适用;要处理 Binlog 顺序与数据一致性;冷库写入可能落后于热库。

5.2 三种方案的对比与选型

特性同步双写写入 MQ 分发Binlog 同步 (CDC)
实现难度高,需要分布式事务中,需要 MQ 组件与消息消费逻辑中,需要部署 Canal 等组件
数据一致性保证最强(事务级别原子)较强,但需处理消息顺序与重试较强,但需保证 Binlog 顺序
编码侵入性大,需改造所有写逻辑小,写操作统一发 MQ,读写分离最小,几乎无需改写业务代码
延迟几毫秒到几十毫秒几十毫秒到几百毫秒几十毫秒到几百毫秒
组件依赖依赖分布式事务管理依赖 MQ(Kafka/RocketMQ 等)依赖 Canal/Maxwell 等工具
  • 推荐场景

    • 小规模新项目:若对一致性要求极高,可考虑同步双写;
    • 成熟项目迁移:若无法改造业务代码,偏好无侵入式方案,可优先采用 Binlog 同步;
    • 复杂业务多订阅:若冷库的使用场景很多(搜索、统计、离线计算),可使用 MQ 分发 → 多消费者并行处理。

6. 思维发散:结果缓存池与其他复用技术

除了上述结构与时间维度的“变小”策略,还有诸多“优化思想”,可将大对象或复杂操作“预先计算/预先组织”,减少运行时开销。

6.1 数据库索引(B+ 树)

  • 场景:表中亿级别数据时,若无索引,每次 WHERE 条件查询都需全表扫描;
  • 优化:创建 B+ 树索引,将热点列或联合列组织成树状结构,对磁盘页预读更友好;查询时只需 O(logN) 查找到对应行所在页,再读取该页;
  • 效果:大幅减少磁盘 I/O,真实查询只需读取少量页。

6.2 序列化协议:JSON vs Protobuf

  • JSON/XML:可读性好,但体积与解析开销大。

  • Protobuf(Protocol Buffers)

    • 二进制格式,轻量紧凑:序列化后的字节数只有 JSON 的约 1/10;

    • 解析速度快:相比 Jackson/Gson 解析 JSON,Protobuf 解析更高效;

    • 使用示例:

      message User {int32 id = 1;string name = 2;int32 age = 3;string email = 4;
      }
      
    • Java 端使用自动生成的 UserProto.User.parseFrom(byte[]) 快速解析;

6.2.1 性能比较

  • 体积:若同样的数据,Protobuf 序列化后大小为 JSON 的 1/10~1/20;
  • 反序列化速度:Protobuf 可以提升 5~100 倍的解码性能;
  • 应用场景:RPC 通信、海量日志传输、缓存存储(如 Redis 存二进制)。

7. 小结

从“大对象优化”角度,系统梳理了多种有效策略:

  1. String substring 内存泄漏案例

    • JDK6 substring() 会引用原始大 char[],导致堆内存泄漏;
    • JDK7+ 已修复为复制子串,避免大数组被长期引用;
  2. 集合扩容的隐形成本

    • StringBuilderArrayListHashMap 扩容都会触发“新数组分配 + 数据复制 + (若为 HashMap)重新散列”;
    • 提前预估容量、使用带容量构造参数或批量插入可显著减少扩容次数,提升性能;
  3. 结构维度优化

    • 合理粒度:以用户信息为例,用 Redis Hash 代替 JSON 字符串,针对性地查询/更新单字段;
    • Bitmap 压缩:将大规模布尔标志(如性别、签到状态、活跃标识)转换为紧凑的 Bitmap,显著节省内存;
    • 布隆过滤器:在判断元素是否存在场景下,用少量内存做好“判断一定不存在” → 减少缓存/数据库访问;
  4. 时间维度优化(冷热分离)

    • 同步双写(分布式事务):最严谨但改造成本高;
    • MQ 异步分发:解耦写逻辑,适合多订阅、批量写入场景;
    • Binlog 同步(CDC):低侵入、可实时同步事务日志到冷库;
  5. 结果缓存池思维

    • 缓存与池化的共通本质:“预先做高成本操作并保留结果,下次复用”
    • 进一步延伸至数据库索引(B+ 树)、Protobuf 序列化等优化,大幅减少运行时 I/O 与解析开销。

通过以上多维度优化手段,我们能够:

  • 减少大对象在堆内的驻留,降低 GC 压力;
  • 避免不必要的网络/磁盘传输,节省带宽与 I/O 等待;
  • 聚焦操作于必要子集,降低 CPU 解析成本;
  • 做到“热数据”快速命中,“冷数据”按需访问,兼顾性能与成本。

在这里插入图片描述


http://www.hkcw.cn/article/CwtBwAgphX.shtml

相关文章

尹锡悦夫妇公开露面参加大选投票 完成投票未回应提问

韩国第21届总统选举于当地时间3日上午6时正式开始投票。据韩联社报道,当天上午,韩国前总统尹锡悦与夫人金建希在安保人员陪同下前往首尔瑞草区的一处投票站完成投票。投票结束后,面对记者关于“何时接受检方调查”、“如何看待因弹劾引发的提前大选”以及“为何拒绝配合调查…

专家:国际调解院不是和西方打擂台 60国代表齐聚香港

国际调解院不是和西方打擂台 60国代表齐聚香港!调解不再看西方脸色,60国代表齐聚香港。2025年,中国主导设立的“国际调解院”正式挂牌成立,总部设在香港的旧湾仔警署。来自亚洲、非洲、中东等60个国家的代表共同见证这一历史性时刻。印尼外长表示:“终于不用再花冤枉钱看欧…

中纪委发布5月反腐月报 97人被查41人被处分

6月2日下午,中纪委网站发布《反腐月报》显示,5月共有97人被查,41人被处分。在被查的97人中,包括7名中管干部。这些中管干部分别为:十四届全国政协常委、经济委员会副主任毕井泉,国家国防科技工业局原党组成员、副局长张建华,陕西省政协副主席刘宽忍,四川省政府党组成员…

易烊千玺《酱园弄》光头造型 角色海报引热议

6月3日,《酱园弄》官方宣布该片第一部将于6月21日上映。预告片中,章子怡饰演的詹周氏身着破碎染血旗袍提包走过弄堂,周围的人们神情各异,雷佳音饰演的薛至武在她即将走出弄堂时伸手阻拦,詹周氏的命运充满未知。海报上,詹周氏站在中心,众人围绕在她周围,底部露出的报纸文…

韩国大选 尹锡悦夫妇完成投票

韩国第21届总统选举于当地时间3日上午6时正式开始投票。据韩联社报道,韩国前总统尹锡悦与夫人金建希当天上午在安保人员陪同下前往首尔瑞草区的一处投票站完成投票。投票结束后,面对记者关于“何时接受检方调查”“如何看待因弹劾引发的提前大选”“为何拒绝配合调查”等问题…

妈妈给萌娃哭声配音看笑网友:好贴心,还给孩子留了气口..

孩子妈:自从学会了配音,再也不担心孩子哭了,网友:好贴心,还给孩子留了气口...责任编辑:zx0002

媒体:别让装备竞赛绑架青少年 碳板鞋风靡校园引忧虑

近段时间,碳板鞋开始风靡校园,成为学生们的“新宠”。这类鞋子外观炫酷、科技感十足,但其流行背后隐藏着不少问题。碳板鞋最初设计是为了提高精英运动员的运动水平,但在校园里却成了学生们展示个性和时尚的方式,甚至形成了鄙视链,国际品牌高于国产品牌高于杂牌,普通运动…

cpper 转 Golang

推荐视频 8小时转职Golang工程师(如果你想低成本学习Go语言) 文章目录 与C对比Go语言基本语法特殊类型与占位符:defer数组 slice切片map[string]stringstruct 结构体继承interface 多态 机制调度器GPM&#xff1a;M:N 调度器&#xff08;多对多调度器&#xff09; runtime全局G…

Linux如何区分普通进程和实时进程

在 Linux 中&#xff0c;区分普通进程&#xff08;Normal Process&#xff09;和实时进程&#xff08;Real-Time Process&#xff09;主要通过以下两个核心机制实现&#xff1a; 1. 调度策略&#xff08;Scheduling Policy&#xff09; Linux 使用 调度策略明确标识进程类型&a…

学院校园网三层架构详解配置实战:从拓扑到策略全解析

目录 一、项目背景与网络拓扑 1.1 网络架构概述 1.2 物理拓扑结构 二、IP地址规划与VLAN划分 2.1 IP地址分配表 2.2 VLAN规划策略 三、设备配置详解 3.1 出口路由器R1配置 3.1.1 基础配置 3.1.2 路由配置 3.1.3 NAT配置 3.1.4 R2配置 3.2 核心交换机S1配置 3.2.…

长期喝桶装水或面临健康风险 微塑料隐患需警惕

在日常生活中,有人习惯于长期自己烧水喝,也有一部分人对自来水的水质问题担忧,选择桶装水或瓶装水。那么,长期自己烧水喝的人和经常买桶装水喝的人,到底谁更健康?2024年1月,国际学术期刊《美国国家科学院院刊》发表了一项最新研究发现:每升瓶/桶装水中平均约含有24万个…

《酱园弄》第一部群星海报来啦!

《酱园弄》第一部群星海报来啦!真相无踪、命数未定,海报更是信息量满满,好了这下暑假有电影看了。责任编辑:zx0002

多人殴打未成年人被抓获 最小15岁 7人全部落网

多人殴打未成年人被抓获 最小15岁 7人全部落网!6月2日,四川古蔺警方通报了一起在地下停车场发生的多人殴打未成年人事件。警方成功抓获了7名涉案人员,其中年龄最大的26岁,最小的15岁。目前,已有2人被刑事拘留,另外5人受到行政处罚。责任编辑:0882

水果夹酸奶风靡长沙 成餐饮新宠

水果夹酸奶风靡长沙 成餐饮新宠。继“干噎酸奶”风靡网络后,“水果夹酸奶”成为近期的热门甜品。新鲜的草莓、菠萝蜜、苹果、葡萄甚至是荔枝和蓝莓切开,加入适量酸奶,吸引了许多消费者前来品尝。在长沙,数十家酸奶、甜品店纷纷推出这款新品,一些湘菜馆和料理店也特意增加了…

汽车行业的价格战该“刹车”了 无序竞争损害行业健康发展

“618”限时促销活动中,部分国内车企大幅降价,最高直降5.3万元。这轮价格战始于5月23日,一家车企因市场中涌入更多有竞争力的对手,以及冲销量的考虑,率先发起大规模降价活动。随后多家车企纷纷效仿,市场上出现了连锁反应。根据公开信息,超过半数的主流车企发布了不同程度…

window/linux ollama部署模型

模型部署 模型下载表: deepseek-r1 win安装ollama 注意去官网下载ollama,这个win和linux差别不大,win下载exe linux安装ollama 采用docker方式进行安装: OLLAMA_HOST=0.0.0.0:11434 \ docker run -d \--gpus all \-p 11434:11434 \--name ollama \-v ollama:/root/.ol…

黑马Java面试笔记之 微服务篇(SpringCloud)

一. SpringCloud 5大组件 SpringCloud 5大组件有哪些&#xff1f; 总结 五大件分别有&#xff1a; Eureka&#xff1a;注册中心Ribbon&#xff1a;负载均衡Feign&#xff1a;远程调用Hystrix&#xff1a;服务熔断Zuul/Gateway&#xff1a;网关 如果项目用到了阿里巴巴&#xff…

Dom树相关

对节点的增删改查 查 查看元素节点 document代表整个文档 document.getElementById() //元素id 在Ie8以下的浏览器&#xff0c;不区分id大小写&#xff0c;而且也返回匹配name属性的元素 getElementsByTagName() // 标签名getElementByName(); //&#xff0c;需注意&#xf…

继承(全)

⾯向对象思想中提出了继承的概念&#xff0c;专⻔⽤来进⾏共性抽取&#xff0c;实现代码复⽤。 1.什么是继承 如&#xff1a;狗和猫都是动物&#xff0c;那么我们就可以将共性的内容进⾏抽取&#xff0c;然后采⽤继承的思想来达到共⽤。 // Animal.javapublic class Animal{S…

车主因赖账被代驾举报酒驾 5元停车费引发风波

近日,浙江宁波一名兰博基尼车主酒后请代驾将车开到小区,随后自己开车进车库。因不愿支付代驾小哥垫付的5元停车费,被对方举报酒驾。交警检测发现,该车主血液中的酒精含量达59mg/100ml,达到酒驾标准。其驾驶证被扣12分,暂扣6个月,并被处以2000元以下罚款。事发当晚11时30…