Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >并发设计模式实战系列(8):Active Object

并发设计模式实战系列(8):Active Object

作者头像
摘星.
发布于 2025-05-20 06:48:13
发布于 2025-05-20 06:48:13
13400
代码可运行
举报
文章被收录于专栏:博客专享博客专享
运行总次数:0
代码可运行
🌟 大家好,我是摘星! 🌟

今天为大家带来的是并发设计模式实战系列,第8章Active Object,废话不多说直接开始~

一、核心原理深度拆解

1. 对象与执行解耦架构
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
┌───────────────┐    ┌─────────────────┐    ┌───────────────┐
│   Client       │    │   Method Request │    │   Scheduler    │
 (同步调用接口)  │───> (方法封装对象)    │───> (任务调度器)   │
└───────────────┘    └─────────────────┘    └───────────────┘
       ▲                                         │
       │                                         ▼
       │                                  ┌───────────────┐
       └─────────────────────────────────│   Servant      │
                                          (实际执行体)   │
                                         └───────────────┘
2. 核心组件
  • Proxy:提供与普通对象相同的接口,将方法调用转为Method Request对象
  • Method Request:封装方法调用信息(命令模式)
  • Scheduler:维护请求队列,按策略调度执行(通常基于线程池)
  • Servant:实际执行业务逻辑的对象
  • Future:异步返回结果的占位符

二、生活化类比:餐厅订餐系统

系统组件

现实类比

核心行为

Client

顾客

下单但不参与烹饪过程

Proxy

服务员

接收订单并转交后厨

Scheduler

厨师长

安排厨师处理订单队列

Servant

厨师团队

实际烹饪操作

Future

取餐号码牌

凭此后续获取菜品

  • 异步流程:顾客下单 → 服务员记录 → 订单进入队列 → 厨师按序处理 → 完成通知

三、Java代码实现(生产级Demo)

1. 完整可运行代码
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import java.util.concurrent.*;

// 1. 定义业务接口
interface MyService {
    Future<String> process(String data) throws InterruptedException;
}

// 2. 实现Servant(实际执行体)
class MyServant implements MyService {
    @Override
    public String doProcess(String data) throws InterruptedException {
        Thread.sleep(1000); // 模拟耗时操作
        return "Processed: " + data.toUpperCase();
    }
}

// 3. 方法请求封装(Command模式)
class MethodRequest implements Callable<String> {
    private final MyServant servant;
    private final String data;

    public MethodRequest(MyServant servant, String data) {
        this.servant = servant;
        this.data = data;
    }

    @Override
    public String call() throws Exception {
        return servant.doProcess(data);
    }
}

// 4. Active Object代理
class MyServiceProxy implements MyService {
    private final ExecutorService scheduler = 
        Executors.newSingleThreadExecutor(); // 可替换为线程池
    
    private final MyServant servant = new MyServant();

    @Override
    public Future<String> process(String data) {
        System.out.println("[Proxy] 接收请求: " + data);
        Future<String> future = scheduler.submit(new MethodRequest(servant, data));
        System.out.println("[Proxy] 已提交任务队列");
        return future;
    }

    public void shutdown() {
        scheduler.shutdown();
    }
}

// 5. 客户端使用
public class ActiveObjectDemo {
    public static void main(String[] args) throws Exception {
        MyService service = new MyServiceProxy();
        
        // 异步调用
        Future<String> future1 = service.process("hello");
        Future<String> future2 = service.process("world");

        System.out.println("[Client] 提交任务后立即继续其他操作...");
        
        // 获取结果(阻塞直到完成)
        System.out.println("[Client] 结果1: " + future1.get());
        System.out.println("[Client] 结果2: " + future2.get());

        ((MyServiceProxy)service).shutdown();
    }
}
2. 关键配置说明
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 调度器优化:使用带容量的线程池
ThreadPoolExecutor scheduler = new ThreadPoolExecutor(
    1, // 核心线程
    4, // 最大线程
    30, TimeUnit.SECONDS,
    new ArrayBlockingQueue<>(100), // 防止无限制堆积
    new ThreadPoolExecutor.CallerRunsPolicy()
);

// Future增强:使用CompletableFuture
public Future<String> process(String data) {
    CompletableFuture<String> future = new CompletableFuture<>();
    scheduler.execute(() -> {
        try {
            String result = servant.doProcess(data);
            future.complete(result);
        } catch (Exception e) {
            future.completeExceptionally(e);
        }
    });
    return future;
}

四、横向对比表格

1. 并发模式对比

模式

线程管理

调用方式

适用场景

Active Object

集中调度

异步调用

需要方法调用顺序控制

Half-Sync/Half-Async

分层管理

混合调用

高并发I/O+阻塞任务混合

Thread-Per-Request

每次新建线程

同步调用

简单短任务

Reactor

事件驱动

非阻塞

纯高并发网络I/O处理

2. 任务队列策略对比

特性

Active Object

普通线程池

调用控制

方法级封装

Runnable/Callable

顺序保证

严格队列顺序

可配置优先级

异常处理

通过Future获取

自行捕获处理

资源管理

集中调度可控

依赖线程池配置


五、高级优化技巧

1. 优先级调度实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class PriorityMethodRequest implements Comparable<PriorityMethodRequest>, Callable<String> {
    private int priority; // 优先级字段
    
    @Override
    public int compareTo(PriorityMethodRequest o) {
        return Integer.compare(o.priority, this.priority);
    }
}

// 使用PriorityBlockingQueue
ThreadPoolExecutor scheduler = new ThreadPoolExecutor(
    1, 4, 30, TimeUnit.SECONDS,
    new PriorityBlockingQueue<>(100)
);
2. 方法调用超时控制
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Future<String> future = service.process("data");
try {
    String result = future.get(2, TimeUnit.SECONDS); // 设置超时
} catch (TimeoutException e) {
    future.cancel(true); // 取消任务
}
3. 性能监控指标
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 监控队列积压
int queueSize = ((ThreadPoolExecutor)scheduler).getQueue().size();

// 跟踪方法执行时间
long start = System.nanoTime();
String result = servant.doProcess(data);
long duration = System.nanoTime() - start;

六、模式变体与扩展应用

1. 多线程Active Object变体
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 扩展为多消费者线程池
class MultiThreadActiveObject implements MyService {
    private final ExecutorService scheduler = 
        Executors.newFixedThreadPool(4); // 多线程调度
    
    // ...其余实现与单线程版本相同...
}

// 适用场景:CPU密集型任务处理
2. 事件驱动融合方案
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
┌───────────────┐    ┌─────────────────┐    ┌───────────────┐
│   Event        │    │   Active Object   │    │   Reactor     │
│   Producer     │───>   (带队列缓冲)    │───>   (非阻塞I/O) │
└───────────────┘    └─────────────────┘    └───────────────┘
  • 组合优势:突发流量缓冲 + 高效I/O处理
  • 实现要点
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class EventDrivenActiveObject {
    private final BlockingQueue<Event> eventQueue = new LinkedBlockingQueue<>();
    private final Reactor reactor = new Reactor();
    
    public void onEvent(Event event) {
        eventQueue.offer(event);
    }
    
    private void processEvents() {
        while (true) {
            Event event = eventQueue.take();
            reactor.handleEvent(event); // 转交Reactor处理
        }
    }
}

七、生产环境最佳实践

1. 异常处理增强方案
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class RobustMethodRequest implements Callable<String> {
    @Override
    public String call() {
        try {
            return servant.doProcess(data);
        } catch (Exception e) {
            // 1. 记录详细上下文信息
            // 2. 触发补偿机制
            // 3. 返回兜底结果
            return "FallbackResult";
        }
    }
}

// 使用装饰器模式统一处理
public Future<String> process(String data) {
    FutureTask<String> task = new FutureTask<>(
        new ExceptionHandlingDecorator(
            new MethodRequest(servant, data)
        )
    );
    scheduler.execute(task);
    return task;
}
2. 动态降级策略
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 根据系统负载动态调整
class AdaptiveScheduler {
    private final ThreadPoolExecutor executor;
    
    public void adjustPoolSize() {
        if (systemOverloaded()) {
            executor.setCorePoolSize(2); // 降级处理
        } else {
            executor.setCorePoolSize(8); // 正常处理
        }
    }
    
    private boolean systemOverloaded() {
        return executor.getQueue().size() > 50 
               || SystemLoadAverage() > 2.0;
    }
}

八、性能调优指南

1. 关键参数配置矩阵

参数

低负载场景

高并发场景

计算密集型场景

核心线程数

CPU核数

CPU核数×2

CPU核数+1

队列容量

100-500

1000-5000

100-200

拒绝策略

CallerRuns

DiscardOldest

AbortPolicy

优先级策略

关闭

业务分级启用

计算优先级启用

2. 监控指标看板
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 通过JMX暴露关键指标
class ActiveObjectMetrics implements ActiveObjectMetricsMBean {
    public int getQueueSize() {
        return executor.getQueue().size();
    }
    
    public double getAvgProcessTime() {
        return timer.getMeanRate();
    }
}

// 注册MBean
ManagementFactory.getPlatformMBeanServer()
    .registerMBean(new ActiveObjectMetrics(), name);

九、常见陷阱与规避方案

1. 死锁场景分析
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
┌───────────────┐        ┌───────────────┐
│  Client Thread │        │  Active Object │
   (持有锁A)  (等待锁B)     │
│   request1()   │───────>│  正在执行      │
└───────────────┘        └───────────────┘
    ↑                         ↑
    │  request2()需要锁B      │ 需要锁A继续执行
    └─────────────────────────┘

解决方案

  • 避免在Servant方法中调用其他Active Object
  • 使用超时获取锁:lock.tryLock(100, TimeUnit.MILLISECONDS)
2. 内存泄漏防范
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 弱引用持有Future
private final Map<Future<?>, WeakReference<Context>> contextMap = 
    new ConcurrentHashMap<>();

// 定期清理已完成任务
scheduler.scheduleAtFixedRate(() -> {
    contextMap.entrySet().removeIf(e -> 
        e.getKey().isDone() || e.getValue().get() == null
    );
}, 1, 1, TimeUnit.HOURS);

十、行业应用案例

1. 金融交易系统实现
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
┌───────────────────────┐
│  订单接收 (Active Object) │
├───────────────────────┤
│ 1. 验证请求合法性        │
│ 2. 生成交易流水号        │
│ 3. 进入风险控制队列      │
└───────────────┬───────┘
                ↓
┌───────────────────────┐
│  风控处理 (优先级队列)    │
├───────────────────────┤
│ • VIP客户优先处理       │
│ • 黑名单实时拦截         │
└───────────────────────┘
2. 物联网设备管理
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class DeviceManagerProxy implements DeviceAPI {
    // 设备命令按优先级处理
    private final PriorityBlockingQueue<Command> queue;
    
    public Future<Result> sendCommand(Device device, Command cmd) {
        HighPriorityCommand wrappedCmd = 
            new HighPriorityCommand(device, cmd);
        return scheduler.submit(wrappedCmd);
    }
    
    private class HighPriorityCommand implements Comparable<HighPriorityCommand> {
        // 根据设备类型设置优先级
        public int compareTo(HighPriorityCommand o) {
            return this.device.isCritical() ? 1 : -1;
        }
    }
}

通过这十个维度的系统化解析,Active Object模式可覆盖从基础实现到高级优化的全场景需求。关键点总结:

  1. 解耦价值:分离方法调用与执行
  2. 调度控制:通过队列实现流量整形
  3. 扩展能力:支持优先级/超时等企业级需求
  4. 行业适配:可根据领域特性定制变体
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-04-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
RS232 串行通信:C++ 实现指南
在现代嵌入式系统和工业控制领域,RS232 串行通信仍然是一种不可或缺的技术。尽管 USB 和以太网等高速通信技术已经广泛应用,但在一些需要低速、简单通信的场景中,RS232 仍然是首选。本文将详细介绍如何在 C++ 中实现与 RS232 的通信,包括 Windows 和 Linux 平台的实现方法。
码事漫谈
2025/04/21
1340
RS232 串行通信:C++ 实现指南
详解RS232、RS485、RS422、串口和握手
计算机与计算机或计算机与终端之间的数据传送可以采用串行通讯和并行通讯二种方式。由于串行通讯方式具有使用线路少、成本低,特别是在远程传输时,避免了多条线路特性的不一致而被广泛采用。
不脱发的程序猿
2021/01/20
2.3K0
RS232不就是接RTX和DTX两根线吗?那你还接其他的(RTS、CTS等)干嘛呢?
基本上,谈到串行通讯,两线制的线缆,一般都是这两根线缆。这里小测试下,哪位朋友能准确知道这两个接口的英文全称呢?
Hello工控
2024/06/25
7920
RS232不就是接RTX和DTX两根线吗?那你还接其他的(RTS、CTS等)干嘛呢?
TTL转RS232电路–分享原理图和参考资料
RS232串口经常用到,本文分享下RS232协议方面基本点,并介绍一种简单的串口TTL(3.3V)电平转换为RS232电平的电路,这个电路是经过制板验证过的。 使用芯片MAX3232E (tssop16封装),电源用3.3V,电路如下图
全栈程序员站长
2022/07/22
2.7K0
TTL转RS232电路–分享原理图和参考资料
RS232串行通信全解析(历史、定义、电气特性及功能特性等等)
由于其相对简单和低硬件成本(与并行接口相比),串行通信在电子行业中被广泛使用。今天,最流行的串行通信标准当然是EIA/TIA-232-E规范。该标准由电子工业协会和电信工业协会(EIA/TIA)开发,更普遍地称为简单的RS-232,其中RS代表“推荐标准”。尽管近年来,为了帮助识别标准的来源,该RS前缀已被EIA/TIA取代,但本文使用了通用的RS-232表示法。
Hello工控
2024/06/25
5.6K0
RS232串行通信全解析(历史、定义、电气特性及功能特性等等)
DB9引脚定义_422串口定义
DB9引脚定义_422串口定义DB9串口引脚定义RS-232端(DB9母头/孔型)引脚定义引脚序号      2      3      5      1、4、6      7、8信号定义     TXD    RXD    地     内部相连    内部相连 注:该口可直接插入计算机的COM口2.RS-232端(DB9公头/针型)引脚定义引脚序号      2      3      5    
Java架构师必看
2022/05/03
5.9K0
COM口简介
COM口( cluster communication port )即串行通讯端口。简称串口。因为是采用RS232协议,所以也叫RS232口。有时也叫DB9。
徐师兄
2022/08/29
2K0
COM口简介
moxa串口服务器5430说明书(moxa多串口卡驱动安装)
NPort 5400系列的基本功能是把您现有的串口设备联让您可以轻松方便的将串口设备连接到以太网络。不但保证您现有的硬件资源,更保证您未来的网络扩充的可能性。另外,NPort 5400系列可以轻松的在串口和以太网络之间进行双向的资料传输,让您可以同时达到集中管理串口设备,和在网络中分散管理主机的目的。
全栈程序员站长
2022/07/29
3.8K0
stm32串口USART 硬件流控 --学习笔记
  流控的概念源于 RS232 这个标准,在 RS232 标准里面包含了串口、流控的定义。大家一定了解,RS232 中的“RS”是Recommend Standard 的缩写,即”推荐标准“之意,它并不像 IEEE-1284、IEEE-1394 等标准,是由“委员会定制”。因而,不同的厂商在做 RS232 时,多少会有不同,流控也都会存在差异。以下我们与大家一起探讨流控的作用、搭建及如何操作。
用户6754675
2020/01/07
2.2K0
MCU常见通信总线串讲(二)—— RS232和RS485
首先明确一个概念,关于MCU中通信总线和通信协议,通信总线是一种用于连接各种外设和模块的物理接口,它可以传输数据和控制信息。通信协议则是指在通信总线上传输数据时所遵循的规则和约定,以确保不同设备之间能够正确地交换信息,我们也可以把他叫做通信总线协议。
秋名山码神
2023/11/08
8570
MCU常见通信总线串讲(二)—— RS232和RS485
I2C接口与SPI和UART接口的区别
1、同步通信>异步通信; 2、同步通信时必须有一根时钟线连接传输的两端; 3、都是串行通信方式,并行通信用于内部存储间的通信,如flash; 4、适合传输的距离和通信速率成反比关系;
怪兽
2022/10/04
2.5K0
RK平台 USB转RS485
RS-232是美国电子工业联盟(EIA)制定的串行数据通信的接口标准,原始编号全称是EIA-RS-232(简称232,RS232)。它被广泛用于计算机串行接口外设连接。 RS-232C标准,其中EIA(Electronic Industry Association)代表美国电子工业联盟,RS(Recommended standard)代表推荐标准,232是标识号,C代表RS232的第三次修改(1969年),在这之前,还有RS232B、RS232A. 在RS-232标准中,字符是以一串行的比特串来一个接一个的串列(serial)方式传输,优点是传输线少,配线简单,发送距离可以较远。 最常用的编码格式是异步起停(asynchronous start-stop)格式,它使用一个起始比特后面紧跟7或8个数据比特(bit),然后是可选的奇偶校验比特,最后是一或两个停止比特。所以发送一个字符至少需要10比特,带来的一个好的效果是使全部的传输速率,发送信号的速率以10划分。
全栈程序员站长
2022/08/15
1.3K0
Caché 变量大全 $ZA 变量
$ZA被实现为一系列位标志,每个位表示一条特定的信息。下表显示了可能的值、它们的含义,以及如何使用模(#)和整数除(\)运算符测试它们:
用户7741497
2022/05/11
1.8K1
UART介绍「建议收藏」
UART, Universal Asynchronous Receiver-Transmitter, 通用异步收发器;
全栈程序员站长
2022/10/05
2.1K0
UART介绍「建议收藏」
基于 FPGA 的 UART 控制器设计(VHDL)(中)
今天给大侠带来基于FPGA的 UART 控制器设计(VHDL)(中),由于篇幅较长,分三篇。今天带来第二篇,中篇,RS-232 串口通信简介。话不多说,上货。
FPGA技术江湖
2020/12/30
1.3K0
RS232串口的Windows编程纪要
再次是一篇入门文,各路神仙退散。 直接进入主题,又不是历史课,关于RS232那些前世今生的故事就不摆了。 硬件链接 首先以9针小口为例(大口应当只能去博物馆看了吧)看一下管脚排布,其实RS232本身没进博物馆都已经够让我惊讶了。 (图片来自互联网) 通常使用的接线图: (图片来自互联网) 硬件接口部分的重点: 绝大多数情况下,我们只需要接2号、3号、5号,RXD/TXD/SG三根线就能正常工作。(顺便多说一句,古老的大串口是2、3、7号) 直连模式一般用于延长线或者大小口的转换线。
俺踏月色而来
2018/06/15
1.7K0
RS232的零调制解调器(Null Modem)连接方式,你了解吗?
在RS-232规范中,DTE(数据终端设备)和DCE(数据通信设备)是指串行连接两端的设备类型。一般来说,DTE和DCE分别指计算机设备和调制解调器。因为RS-232规范主要涉及将DTE直接连接到DCE,反之亦然,所以引脚的定义使布线变得简单。
Hello工控
2024/06/25
7790
RS232的零调制解调器(Null Modem)连接方式,你了解吗?
硬件知识:串口通信基础知识介绍
在通信和计算机科学中,串行通信(Serial Communication)是一个通用概念,泛指所有的串行的通信协议,如RS232、RS422、RS485、USB、I2C、SPI等。
小明互联网技术分享社区
2023/01/08
3.7K0
硬件知识:串口通信基础知识介绍
串口通信-MSComm控件使用详解
MSComm 控件通过串行端口传输和接收数据,为应用程序提供串行通讯功能。MSComm控件在串口编程时非常方便,程序员不必去花时间去了解较为复杂的API函数,而且在VC、VB、Delphi等语言中均可使用。 Microsoft Communications Control(以下简称MSComm)是Microsoft公司提供的简化Windows下串行通信编程的ActiveX控件,它为应用程序提供了通过串行接口收发数据的简便方法。具体的来说,它提供了两种处理通信问题的方法:一是事件驱动(Event-driven)方法,一是查询法。
全栈程序员站长
2022/11/15
4K0
Linux串口编程示例
termios是用于终端I/O的较新(现在已经有几十年历史)Unix API。在termios的帮助下执行串行I/O的程序剖析如下:
知否知否应是绿肥红瘦
2025/02/19
9620
Linux串口编程示例
推荐阅读
相关推荐
RS232 串行通信:C++ 实现指南
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验