事件驱动架构设计思路和笔记

news/2026/1/20 14:27:10/文章来源:https://www.cnblogs.com/ljqcii/p/19506487

事件驱动架构完整学习指南

作者: smj 

日期: 2025-01-20  

版本: V1.0  

项目: HCMS-WMS 机器人管理模块 V3.0


📚 目录

  1. 核心概念

  2. 三大核心类详解

  3. 完整工作流程

  4. 代码实战示例

  5. 设计模式深入

  6. 性能优化要点

  7. 常见问题FAQ

  8. 扩展知识


🎯 核心理解图

监听器实现接口 → 重写propertyChange()方法 → 注册到事件总线                                                    ↓                                            事件总线存储监听器                                                    ↓业务类发布事件 → 调用事件总线的firePropertyChange()                                                    ↓                                    事件总线遍历所有注册的监听器                                                    ↓                                            匹配事件模式                                                    ↓                                调用监听器的propertyChange()方法                                                    ↓                                            执行业务逻辑

核心概念

什么是事件驱动架构?

事件驱动架构(Event-Driven Architecture, EDA)是一种软件设计模式,系统中的组件通过发布事件和订阅事件来进行通信,而不是直接调用彼此的方法。

核心角色

┌─────────────┐      发布事件      ┌─────────────┐      通知      ┌─────────────┐

│  发布者     │ ───────────────→  │  事件总线   │ ───────────→  │  监听器     │

│ (Publisher) │                    │ (Event Bus) │                │ (Listener)  │

└─────────────┘                    └─────────────┘                └─────────────┘

   业务服务类                         中介/容器                      处理业务逻辑

三大角色

  • 发布者(Publisher):发布事件的组件(如业务服务类)

  • 事件总线(Event Bus):管理监听器和分发事件的中介

  • 监听器(Listener):订阅事件并处理业务逻辑的组件

为什么使用事件驱动架构?

优点

  • 解耦:发布者和监听器互不依赖,降低耦合度

  • 扩展性:新增监听器不影响现有代码

  • 异步处理:事件发布后立即返回,不阻塞主流程

  • 灵活性:一个事件可以被多个监听器处理

缺点

  • 调试困难:事件流程不直观,需要追踪事件链路

  • 性能开销:事件分发和异步处理有一定开销

  • 事件丢失风险:需要持久化机制保证可靠性


三大核心类详解

1. WmsEventBus - 事件总线

职责

  • 管理所有监听器(注册/移除)

  • 接收事件发布请求

  • 匹配事件模式

  • 异步通知监听器

核心数据结构

// 存储监听器的容器

private final Map<String, List> listeners = new ConcurrentHashMap<>();

//                 ↑                    ↑

//            事件模式(Key)      监听器列表(Value)

// 示例数据:

// {

//     "wms:in:*": [RobotScheduleListener, LoggingListener],

//     "wms:out:*": [RobotScheduleListener, InventoryListener],

//     "wms:robot:*": [MonitoringListener]

// }

为什么用 ConcurrentHashMap?

  • 多线程环境下保证线程安全

  • 支持高并发读写操作

  • 避免数据竞争和不一致

核心方法

1. 注册监听器

public void addPropertyChangeListener(String pattern, PropertyChangeListener listener) {

    listeners.computeIfAbsent(pattern, k -> new CopyOnWriteArrayList<>()).add(listener);

    log.info("监听器已注册: pattern={}, listener={}", pattern, listener.getClass().getSimpleName());

}

关键点

  • computeIfAbsent:如果key不存在,创建新列表;存在则返回现有列表

  • CopyOnWriteArrayList:写时复制列表,适合读多写少场景

  • 支持同一个监听器订阅多个事件模式

2. 发布事件

public void firePropertyChange(String eventName, Object oldValue, Object newValue) {

    PropertyChangeEvent event = new PropertyChangeEvent(this, eventName, oldValue, newValue);

    // 遍历所有注册的监听器

    for (Map.Entry<String, List> entry : listeners.entrySet()) {

        String pattern = entry.getKey();

        // 匹配事件模式

        if (matches(pattern, eventName)) {

            // 异步通知每个监听器

            for (PropertyChangeListener listener : entry.getValue()) {

                executor.submit(() -> notifyListener(listener, event));

            }

        }

    }

}

执行流程

1. 创建事件对象    ↓2. 遍历所有监听器    ↓3. 匹配事件模式(通配符支持)    ↓4. 使用虚拟线程异步通知    ↓5. 调用监听器的 propertyChange() 方法
3. 通配符匹配

private boolean matches(String pattern, String eventName) {

    if (pattern.equals(eventName)) {

        return true;  // 完全匹配

    }

    if (pattern.endsWith("*")) {

        String prefix = pattern.substring(0, pattern.length() - 1);

        return eventName.startsWith(prefix);  // 前缀匹配

    }

    return false;

}

匹配规则

matches("wms:in:*", "wms:in:start")     → true  ✅ 前缀匹配matches("wms:in:*", "wms:in:complete")  → true  ✅ 前缀匹配matches("wms:in:*", "wms:out:start")    → false ❌ 前缀不匹配matches("wms:in:start", "wms:in:start") → true  ✅ 完全匹配

虚拟线程优化

// 构造方法中初始化线程池

public WmsEventBus() {

    ExecutorService executor;

    try {

        // Java 21+ 使用虚拟线程

        Method virtualThreadMethod = Executors.class.getMethod("newVirtualThreadPerTaskExecutor");

        executor = (ExecutorService) virtualThreadMethod.invoke(null);

        log.info("使用虚拟线程池");

    } catch (Exception e) {

        // 降级到普通线程池

        executor = Executors.newFixedThreadPool(10);

        log.info("使用普通线程池");

    }

    this.executor = executor;

}

虚拟线程 vs 普通线程

| 特性 | 虚拟线程 | 普通线程 |

|------|---------|---------|

| 创建成本 | 极低 | 高 |

| 内存占用 | 几KB | 1-2MB |

| 数量限制 | 百万级 | 几千个 |

| 适用场景 | 高并发I/O | CPU密集型 |


2. WmsEventPersistence - 事件持久化服务

职责

  • 将事件保存到数据库

  • 提供故障恢复能力

  • 支持事件重试机制

  • 记录事件处理状态

核心方法

1. 保存事件

@Transactional(rollbackFor = Exception.class)

public String saveEvent(String eventName, String businessId, String businessType, String eventData) {

    WmsEventLog eventLog = new WmsEventLog();

    eventLog.setEventName(eventName);

    eventLog.setBusinessId(businessId);      // 业务单号

    eventLog.setBusinessType(businessType);  // 业务类型

    eventLog.setEventData(eventData);        // 事件数据(JSON)

    eventLog.setStatus(EventStatusEnum.PENDING.getCode());

    eventLog.setRetryCount(0);

    eventLogMapper.insert(eventLog);

    return eventLog.getId();

}

使用场景

// 入库单开始时保存事件String eventId = wmsEventPersistence.saveEvent("wms:in:start",           // 事件名称"IN202501200001",         // 入库单号"INBOUND",                // 业务类型JSON.toJSONString(order)  // 事件数据);
2. 更新事件状态

@Transactional(rollbackFor = Exception.class)

public void updateEventStatus(String eventId, EventStatusEnum status, String errorMessage) {

    WmsEventLog eventLog = eventLogMapper.selectById(eventId);

    eventLog.setStatus(status.getCode());

    eventLog.setUpdateTime(new Date());

    if (status == EventStatusEnum.FAILED && errorMessage != null) {

        eventLog.setErrorMessage(errorMessage);

    }

    if (status == EventStatusEnum.COMPLETED) {

        eventLog.setProcessedTime(new Date());

    }

    eventLogMapper.updateById(eventLog);

}

状态流转

PENDING(待处理)    ↓PROCESSING(处理中)    ↓COMPLETED(已完成) / FAILED(失败)
3. 扫描未处理事件(故障恢复)

public List scanUnprocessedEvents(int maxRetryCount, int limit) {

    LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>();

    queryWrapper.eq(WmsEventLog::getStatus, EventStatusEnum.PENDING.getCode())

                .lt(WmsEventLog::getRetryCount, maxRetryCount)

                .orderByAsc(WmsEventLog::getCreateTime)

                .last("LIMIT " + limit);

    return eventLogMapper.selectList(queryWrapper);

}

使用场景

// 系统重启后,扫描未处理的事件重新处理@Scheduled(fixedDelay = 60000)  // 每分钟执行一次public void recoverUnprocessedEvents() {List<WmsEventLog> events = wmsEventPersistence.scanUnprocessedEvents(3, 100);for (WmsEventLog event : events) {// 重新发布事件wmsEventBus.firePropertyChange(event.getEventName(), null, event.getEventData());// 更新状态为处理中wmsEventPersistence.updateEventStatus(event.getId(), EventStatusEnum.PROCESSING, null);}}
4. 重试失败事件

@Transactional(rollbackFor = Exception.class)

public boolean retryEvent(String eventId) {

    WmsEventLog eventLog = eventLogMapper.selectById(eventId);

    // 增加重试次数

    eventLog.setRetryCount(eventLog.getRetryCount() + 1);

    // 重置状态为PENDING

    eventLog.setStatus(EventStatusEnum.PENDING.getCode());

    eventLog.setUpdateTime(new Date());

    eventLogMapper.updateById(eventLog);

    return true;

}

---### 3. WmsEventNames - 事件名称常量#### 职责- 统一管理所有事件名称- 避免硬编码和拼写错误- 提供工具方法判断事件类型#### 命名规范

wms:{业务模块}:{操作}

**示例**:- `wms:in:start` - 入库开始- `wms:out:complete` - 出库完成- `wms:robot:task:finish` - 机器人任务完成#### 核心常量// 入库相关public static final String INBOUND_START = "wms:in:start";public static final String INBOUND_COMPLETE = "wms:in:complete";public static final String INBOUND_CANCEL = "wms:in:cancel";// 出库相关public static final String OUTBOUND_START = "wms:out:start";public static final String OUTBOUND_COMPLETE = "wms:out:complete";// 机器人相关public static final String ROBOT_TASK_FINISH = "wms:robot:task:finish";  // 重要!触发自动调度// 通配符模式public static final String INBOUND_ALL = "wms:in:*";public static final String ROBOT_ALL = "wms:robot:*";

工具方法

// 判断是否为业务事件public static boolean isBusinessEvent(String eventName) {return eventName.startsWith("wms:in:")|| eventName.startsWith("wms:out:")|| eventName.startsWith("wms:check:");}// 提取业务类型public static String extractBusinessType(String eventName) {if (eventName.startsWith("wms:in:")) return "INBOUND";if (eventName.startsWith("wms:out:")) return "OUTBOUND";return "UNKNOWN";}

完整工作流程

流程图

[系统启动]

    ↓

[监听器注册]

RobotScheduleListener.init()

wmsEventBus.addPropertyChangeListener("wms:in:*", this)

    ↓

[事件总线存储]

listeners = {

    "wms:in:*": [RobotScheduleListener]

}

    ↓

[用户操作]

POST /api/inbound/create

    ↓

[业务处理]

InboundService.createInbound()

保存入库单到数据库

    ↓

[发布事件]

wmsEventBus.firePropertyChange("wms:in:start", null, order)

    ↓

[事件总线匹配]

遍历listeners

匹配"wms:in:*"和"wms:in:start" ✅

    ↓

[异步通知]

executor.submit(() -> {

    RobotScheduleListener.propertyChange(event)

})

    ↓

[监听器处理]

handleInboundEvent()

查询可用机器人

创建机器人任务

下发任务

### 时序图

用户          Controller      Service       EventBus      Listener

 │               │              │              │             │

 │─创建入库单──→│              │              │             │

 │               │─调用服务──→│              │             │

 │               │              │─保存数据     │             │

 │               │              │─发布事件───→│             │

 │               │              │              │─匹配模式    │

 │               │              │              │─通知监听器→│

 │               │              │              │             │─处理业务

 │               │←返回成功────│              │             │

 │←返回结果────│              │              │             │

---## 代码实战示例### 完整示例:入库流程#### 1. 监听器类package com.slhc.hcms.module.robot.listener;import com.slhc.hcms.module.robot.event.WmsEventBus;import com.slhc.hcms.module.robot.service.IRobotInfoService;import com.slhc.hcms.module.robot.service.IRobotTaskService;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import javax.annotation.PostConstruct;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;@Slf4j@Componentpublic class RobotScheduleListener implements PropertyChangeListener {    @Autowired    private WmsEventBus wmsEventBus;    @Autowired    private IRobotInfoService robotInfoService;    @Autowired    private IRobotTaskService robotTaskService;    // 系统启动时自动注册    @PostConstruct    public void init() {        log.info("========== 开始注册机器人调度监听器 ==========");        // 订阅入库事件        wmsEventBus.addPropertyChangeListener("wms:in:*", this);        log.info("✅ 已订阅入库事件");        // 订阅出库事件        wmsEventBus.addPropertyChangeListener("wms:out:*", this);        log.info("✅ 已订阅出库事件");        // 订阅盘点事件        wmsEventBus.addPropertyChangeListener("wms:check:*", this);        log.info("✅ 已订阅盘点事件");        log.info("========== 监听器注册完成 ==========");    }    // 当事件发生时,这个方法会被自动调用    @Override    public void propertyChange(PropertyChangeEvent evt) {        String eventName = evt.getPropertyName();        Object eventData = evt.getNewValue();        log.info("🔔 收到事件: {}", eventName);        try {            // 根据事件类型分发处理            if (eventName.startsWith("wms:in:")) {                handleInboundEvent(eventName, eventData);            } else if (eventName.startsWith("wms:out:")) {                handleOutboundEvent(eventName, eventData);            } else if (eventName.startsWith("wms:check:")) {                handleCheckEvent(eventName, eventData);            }        } catch (Exception e) {            log.error("处理事件失败: eventName={}, error={}", eventName, e.getMessage(), e);        }    }    // 处理入库事件    private void handleInboundEvent(String eventName, Object eventData) {        log.info("📥 处理入库事件: {}", eventName);        // 1. 查询可用机器人        RobotInfo robot = robotInfoService.findAvailableRobot("WH01");        if (robot == null) {            log.warn("⚠️ 没有可用机器人");            return;        }        // 2. 创建机器人任务        RobotTask task = robotTaskService.createTask(            robot.getId(),            "INBOUND",            eventData.toString()        );        log.info("✅ 机器人任务已创建: taskId={}, robotCode={}", task.getId(), robot.getRobotCode());    }    // 处理出库事件    private void handleOutboundEvent(String eventName, Object eventData) {        log.info("📤 处理出库事件: {}", eventName);        // 类似入库处理逻辑    }    // 处理盘点事件    private void handleCheckEvent(String eventName, Object eventData) {        log.info("📋 处理盘点事件: {}", eventName);        // 类似入库处理逻辑    }}

2. 业务服务类

package com.slhc.hcms.module.inbound.service.impl;import com.slhc.hcms.module.inbound.entity.InboundOrder;import com.slhc.hcms.module.robot.event.WmsEventBus;import com.slhc.hcms.module.robot.event.WmsEventNames;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Transactional;@Slf4j@Servicepublic class InboundServiceImpl {@Autowiredprivate WmsEventBus wmsEventBus;@Transactional(rollbackFor = Exception.class)public void createInbound(InboundOrder order) {log.info("========== 开始创建入库单 ==========");log.info("入库单号: {}", order.getOrderNo());// 1. 保存入库单到数据库saveToDatabase(order);log.info("💾 入库单已保存");// 2. 发布事件(通知其他模块)wmsEventBus.firePropertyChange(WmsEventNames.INBOUND_START,  // 使用常量null,order);log.info("📢 入库开始事件已发布");log.info("========== 入库单创建完成 ==========");}private void saveToDatabase(InboundOrder order) {// 保存逻辑}}

3. 控制器类

package com.slhc.hcms.module.inbound.controller;import com.slhc.hcms.module.inbound.entity.InboundOrder;import com.slhc.hcms.module.inbound.service.impl.InboundServiceImpl;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;@Slf4j@RestController@RequestMapping("/api/inbound")public class InboundController {@Autowiredprivate InboundServiceImpl inboundService;@PostMapping("/create")public Result createInbound(@RequestBody InboundOrder order) {log.info("收到创建入库单请求: {}", order.getOrderNo());inboundService.createInbound(order);return Result.success("入库单创建成功");}}

设计模式深入

观察者模式(Observer Pattern)

事件驱动架构是观察者模式的一种实现。

角色映射

  • Subject(主题) = Event Bus(事件总线)

  • Observer(观察者) = Listener(监听器)

  • notify() = firePropertyChange()

类图

┌─────────────────┐│   EventBus      │├─────────────────┤│ +addListener()  ││ +fireEvent()    │└────────┬────────┘         │ 1         │         │ *┌────────▼────────┐│   Listener      │├─────────────────┤│ +propertyChange()│└─────────────────┘

发布-订阅模式(Pub-Sub Pattern)

与观察者模式的区别

| 特性 | 观察者模式 | 发布-订阅模式 |

|------|-----------|--------------|

| 耦合度 | 主题知道观察者 | 发布者不知道订阅者 |

| 中介 | 无 | 有(事件总线) |

| 通信方式 | 直接调用 | 通过中介 |

| 灵活性 | 较低 | 较高 |

💡 我们的实现更接近发布-订阅模式,因为有事件总线作为中介。


性能优化要点

1. 使用虚拟线程

// Java 21+ 虚拟线程ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor();// 优点:// - 创建成本极低// - 可以创建百万级线程// - 适合I/O密集型任务

2. 异步处理

// 事件发布后立即返回,不等待监听器处理完成wmsEventBus.firePropertyChange("wms:in:start", null, order);// 这里立即返回,监听器在后台异步处理

3. 异常隔离

// 一个监听器异常不影响其他监听器for (PropertyChangeListener listener : listeners) {try {listener.propertyChange(event);} catch (Exception e) {log.error("监听器处理失败: {}", e.getMessage());// 继续处理下一个监听器}}

4. 事件持久化

// 保证事件不丢失wmsEventPersistence.saveEvent(eventName, businessId, businessType, eventData);// 定时扫描未处理事件@Scheduled(fixedDelay = 60000)public void recoverEvents() {List<WmsEventLog> events = wmsEventPersistence.scanUnprocessedEvents(3, 100);// 重新处理}

常见问题FAQ

Q1: PropertyChangeListener是什么?

A: 这是Java标准库提供的一个接口(不是方法),定义了事件监听的契约。

package java.beans;public interface PropertyChangeListener {void propertyChange(PropertyChangeEvent evt);}

任何实现这个接口的类都必须提供propertyChange()方法。

Q2: 为什么要重写propertyChange()方法?

A: 因为事件总线需要调用这个方法来通知监听器。

// 事件总线内部listener.propertyChange(event);  // 调用你重写的方法

Q3: 监听器和事件是什么关系?

A:

  • ❌ 不是"监听器包含事件"

  • ✅ 是"监听器订阅事件"

类比

  • 事件 = 电视节目

  • 监听器 = 观众

  • 订阅 = 观众选择看哪些节目

Q4: 一个监听器可以监听多个事件吗?

A: ✅ 可以!

@PostConstructpublic void init() {wmsEventBus.addPropertyChangeListener("wms:in:*", this);wmsEventBus.addPropertyChangeListener("wms:out:*", this);wmsEventBus.addPropertyChangeListener("wms:check:*", this);}

Q5: 事件总线怎么通知监听器?

A: 通过接口调用

// 事件总线持有监听器对象的引用PropertyChangeListener listener = robotScheduleListener;// 通过接口调用监听器的方法listener.propertyChange(event);  // ← 这就是通知!

Q6: 注册监听器和虚拟线程有什么关系?

A:

  • 注册监听器时:不使用线程(只是把监听器放到Map里)

  • 发布事件时:使用虚拟线程异步通知监听器

Q7: 事件会丢失吗?

A: 可能会。解决方案

  1. 事件持久化:保存到数据库

  2. 定时扫描:扫描未处理事件重新处理

  3. 重试机制:失败事件自动重试


扩展知识

1. Spring的事件机制

Spring也提供了事件驱动机制,与我们的实现类似:

// Spring事件

public class InboundStartEvent extends ApplicationEvent {

    public InboundStartEvent(Object source) {

        super(source);

    }

}

// Spring监听器

@Component

public class RobotScheduleListener {

    @EventListener

    public void handleInboundStart(InboundStartEvent event) {

        // 处理业务

    }

}

// 发布事件

@Autowired

private ApplicationEventPublisher eventPublisher;

eventPublisher.publishEvent(new InboundStartEvent(order));

**对比**:| 特性 | 我们的实现 | Spring事件 ||------|-----------|-----------|| 通配符支持 | ✅ | ❌ || 异步处理 | ✅ | 需要@Async || 事件持久化 | ✅ | ❌ || 学习成本 | 低 | 中 |---### 2. 消息队列(MQ)事件驱动架构的进阶版本是使用消息队列:

发布者 → RabbitMQ/Kafka → 订阅者

```

优点

  • ✅ 更高的可靠性

  • ✅ 支持分布式

  • ✅ 消息持久化

  • ✅ 流量削峰

缺点

  • ❌ 部署复杂

  • ❌ 运维成本高


总结

通过本文档,你应该已经掌握了:

  1. ✅ 事件驱动架构的核心概念和工作原理

  2. ✅ 三大核心类(WmsEventBus、WmsEventPersistence、WmsEventNames)的详细实现

  3. ✅ 完整的事件发布-订阅流程

  4. ✅ 实战代码示例和最佳实践

  5. ✅ 性能优化技巧和常见问题解决方案

  6. ✅ 与Spring事件机制和消息队列的对比

关键要点回顾

  • PropertyChangeListener 是Java标准库的接口,不是方法

  • 监听器 有两个职责:注册自己(@PostConstruct)+ 处理业务(propertyChange方法)

  • 事件总线 通过接口调用通知监听器

  • 虚拟线程 用于异步通知,注册时不使用线程

  • 通配符匹配 支持灵活的事件订阅模式


 

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

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

相关文章

2026年苏州正规灵活用工企业排行榜推荐

2026年苏州正规灵活用工企业排行榜推荐行业痛点分析当前&#xff0c;灵活用工领域面临诸多技术挑战。一方面&#xff0c;企业在招聘和管理临时工、合同工时&#xff0c;往往难以实现高效匹配和精细化管理&#xff1b;另一方面&#xff0c;结算流程复杂且存在合规风险。数据显示…

基于springboot的少数民族交流论坛

运行效果:https://lunwen.yeel.cn/view.php?id=5808 基于springboot的少数民族交流论坛摘要:随着互联网技术的快速发展,我国少数民族交流日益频繁,传统的交流方式已无法满足现代交流需求。本文以Spring Boot框架为…

基于SpringBoot的5种签到打卡设计思路及实现方案

签到打卡的多样性需求 在我们的日常开发工作中,经常会遇到各种签到打卡的需求:日常签到:用户每天签到获取积分奖励 活动签到:线下活动参与者扫码签到 考勤打卡:员工上下班打卡记录 位置打卡:基于地理位置的打卡签…

WX-0813 AI 降噪回音消除模组

一、产品概述WX-0813 是一款高集成度一体化语音处理模组&#xff0c;专为解决音频设备开发中的噪音干扰、回音叠加、功放适配三大核心痛点设计。模组集成 AI 降噪&#xff08;ENC&#xff09;、全双工回音消除&#xff08;AEC&#xff09;、双声道 5W 数字功放三大功能&#xf…

伊朗离我们的距离,竟然比上海飞深圳还近!

提到伊朗&#xff0c;不少人觉得它是遥远中东的神秘国度&#xff0c;却不知它与中国的距离远比想象中更近。 中国新疆塔什库尔干县到伊朗最东边境仅1200多公里&#xff0c;比上海飞深圳的距离还要短。 当下的伊朗正面临内忧外患的动荡局势&#xff0c;但这份动荡从未蔓延至中…

【收藏】提示词工程:大模型应用的核心技术,小白程序员必学的提效秘籍

提示词工程是打通大模型应用落地的核心技术&#xff0c;更是程序员、职场人与大模型高效对话的“通关密钥”。想要让大模型精准完成任务&#xff0c;而非输出“答非所问”的内容&#xff0c;就必须掌握科学设计提示词的方法——用清晰的指令、完整的上下文引导模型&#xff0c;…

昆明市英语雅思培训辅导机构推荐,2026权威出国雅思课程中心学校口碑排行榜 - 苏木2025

随着留学热度持续攀升,雅思考试已成为昆明学子通往世界名校的重要门槛,然而在雅思培训选课过程中,多数考生深陷“优质机构难甄别、提分技巧难掌握、个性化方案缺失”的困境。据云南省教育国际交流协会数据显示,202…

免费的考试软件哪个好?实测指南与避坑技巧

无论是学生自测复盘、教师布置随堂测验,还是企业开展基础内训考核,很多人都想找到一款好用的免费考试软件,却屡屡踩坑:要么功能残缺,连主观题都无法支持;要么弹窗广告泛滥,严重干扰答题节奏;要么稳定性极差,答题…

全球主流双转盘高内涵成像分析系统品牌有哪些?一文掌握双转盘共聚焦高内涵分析系统怎么选择 - 品牌推荐大师1

高内涵成像分析系统是一种结合了高分辨率成像和多参数分析技术的先进工具,广泛应用于生命科学研究、药物开发和细胞生物学等领域。随着技术的不断进步,双转盘共聚焦高内涵分析系统因其高速度、高灵敏度和低光毒性的特…

广西北部湾,将成为未来最繁忙的航运地!

作为西部陆海新通道的关键枢纽&#xff0c;广西北部湾港已经迈入到了千万标箱的大港行列。 由钦州、北海、防城三大港口组成的北部湾港&#xff0c;正通过智能化、自动化转型升级&#xff0c;为这条国际大通道持续注入强劲动力。 2025年截至12月30日&#xff0c;班列开行量达…

深度可分离卷积:轻量化模型与FPGA加速的黄金技术

在深度学习与硬件加速的交叉领域,“轻量化”与“高性能”始终是一对核心矛盾。尤其是在FPGA、嵌入式单片机等资源有限的平台上,传统卷积神经网络的庞大计算量和参数量往往成为落地阻碍。而深度可分离卷积(Depthwise…

2025年国内知名的防雨柜供应商排行榜,智能控制台/卡口监控杆/控制台定做/室外防雨箱/消防中心控制台厂家排行榜 - 品牌推荐师

行业背景:防雨柜市场进入精细化竞争阶段 随着工业4.0与智慧城市建设的推进,防雨柜作为保障户外设备稳定运行的核心装备,市场需求呈现爆发式增长。据行业白皮书统计,2024年国内防雨柜市场规模突破120亿元,年复合增…

医用离心机哪个厂商产品安全性高,安信实验仪器值得关注 - 工业品牌热点

在医疗诊断、生物科研与药物研发的核心环节中,医用离心机作为样本分离提纯的关键设备,其安全性、可靠性与适配性直接关系到实验数据准确性与临床诊断效率。面对市场上良莠不齐的医用离心机产品,医疗机构与科研单位如…

昆明市英语雅思培训辅导机构推荐、2026权威出国雅思课程中心学校口碑排行榜 - 苏木2025

随着昆明国际化进程的加速,雅思考试已成为众多学子出国深造的必经之路,然而在雅思培训市场中,考生普遍面临诸多困境:优质教育机构筛选困难、选课缺乏科学指引、提分技巧掌握不足、个性化备考方案缺失,如何在繁杂的…

2026年电力服务企业甄选:电力维保 / 设计 / 电气试验 / 检修 / 工程实力榜单 - 深度智识库

在新型电力系统建设全面提速、“双碳” 目标持续深化的 2026 年,电力维保、电力设计、电气试验、电力检修、电力工程的服务品质,直接决定着工业生产、市政建设、新能源项目等各类用电场景的安全稳定与节能增效水平。…

秦岭为脊,黄河为脉,陕西是中华文明的根!

陕西是中华文明的重要发祥地之一&#xff0c;文化积淀深厚&#xff0c;历史上先后有十四个朝代在此建都&#xff0c;留下丰富的文物古迹。 多年来&#xff0c;陕西先后发掘遗址千余处&#xff0c;出土了大量珍贵文物和科研标本&#xff0c;既有百万年前的人类遗迹&#xff0c;…

2026年排名靠前的成人自考培训机构推荐,春华教育 - 工业品牌热点

在当今社会,成人自考作为提升学历、实现职业进阶的重要途径,选择一家诚信可靠、辅导优质的机构至关重要。面对市场上鱼龙混杂的成人自考培训机构,如何避开收钱跑路教学敷衍的坑,找到真正能助力拿证的靠谱之选?以下…

2026年1月重庆地区助听器专业选配机构排行:十大品牌厂家测评 - 深度智识库

随着我国老龄化社会加速发展,听力健康问题日益凸显。国家卫生健康委员会最新数据显示,我国65岁以上老年人群中听力损失发生率高达51.3%,而重庆作为人口老龄化率较高的城市,这一问题尤为突出。然而,许多听障人士在…

告别 PPT 熬夜魔咒!宏智树 AI 一键生成学术职场双高分演示文稿

还在为开题报告 PPT 逻辑混乱发愁&#xff1f;还在为论文答辩 PPT 数据排版抓狂&#xff1f;还在为工作汇报 PPT 颜值不够焦虑&#xff1f;作为深耕论文写作科普的教育博主&#xff0c;我实测多款工具后发现&#xff0c;宏智树 AI 科研工具的 AI PPT 功能&#xff0c;堪称学术人…