并发模式:主动对象

wufei123 2025-01-05 阅读:6 评论:0
介绍 主动对象模式是一种并发设计模式,它将方法执行与方法调用解耦。此模式的主要目标是通过在单独的线程中执行操作来引入异步行为,同时向客户端提供同步接口。这是通过消息传递、请求队列和调度机制的组合来实现的。 关键部件...
介绍

主动对象模式是一种并发设计模式,它将方法执行方法调用解耦。此模式的主要目标是通过在单独的线程中执行操作来引入异步行为,同时向客户端提供同步接口。这是通过消息传递、请求队列和调度机制的组合来实现的。

关键部件
  1. proxy:代表客户端的公共接口。更简单地说,这就是客户端将要交互的内容。它将方法调用转换为对活动对象的请求。
  2. 调度器:管理请求队列并确定请求执行的顺序。
  3. servant:包含被调用方法的实际实现。这就是实际计算逻辑的所在。
  4. 激活队列:存储来自代理的请求,直到调度程序处理它们。
  5. future/callback:异步计算结果的占位符。
工作流程
  1. 客户端调用代理上的方法。
  2. 代理创建请求并将其放入激活队列中。
  3. 调度程序接收请求并将其转发给servant执行。
  4. 结果通过 future 对象返回给客户端。
使用案例
  • 需要可预测执行模式的实时系统。
  • gui 应用程序保持主线程响应。
  • 用于处理异步请求的分布式系统。
执行

假设我们需要进行计算,可能是 api 调用、数据库查询等。我不会实现任何异常处理,因为我太懒了。

def compute(x, y):
    time.sleep(2)  # some time taking task
    return x + y
没有活动对象模式

下面是我们如何在不使用主动对象模式的情况下处理并发请求的示例。

import threading
import time


def main():
    # start threads directly
    results = {}

    def worker(task_id, x, y):
        results[task_id] = compute(x, y)

    print("submitting tasks...")
    thread1 = threading.thread(target=worker, args=(1, 5, 10))
    thread2 = threading.thread(target=worker, args=(2, 15, 20))

    thread1.start()
    thread2.start()

    print("doing other work...")

    thread1.join()
    thread2.join()

    # retrieve results
    print("result 1:", results[1])
    print("result 2:", results[2])


if __name__ == "__main__":
    main()
上述方法的缺点
  • 线程管理:直接管理线程会增加复杂性,尤其是随着任务数量的增加。

  • 缺乏抽象:客户端负责管理线程的生命周期,将任务管理与业务逻辑耦合。

  • 可扩展性问题:如果没有适当的队列或调度机制,就无法控制任务执行顺序。

  • 响应能力有限:客户端必须等待线程加入才能访问结果。

使用主动对象模式实现

下面是主动对象模式的 python 实现,使用线程和队列来执行与上面相同的操作。我们将一一介绍每个部分:

methodrequest: 封装方法、参数和用于存储结果的 future。

class methodrequest:
    def __init__(self, method, args, kwargs, future):
        self.method = method
        self.args = args
        self.kwargs = kwargs
        self.future = future

    def execute(self):
        try:
            result = self.method(*self.args, **self.kwargs)
            self.future.set_result(result)
        except exception as e:
            self.future.set_exception(e)

调度程序:在单独的线程中持续处理来自activation_queue的请求。

import threading
import queue


class scheduler(threading.thread):
    def __init__(self):
        super().__init__()
        self.activation_queue = queue.queue()
        self._stop_event = threading.event()

    def enqueue(self, request):
        self.activation_queue.put(request)

    def run(self):
        while not self._stop_event.is_set():
            try:
                request = self.activation_queue.get(timeout=0.1)
                request.execute()
            except queue.empty:
                continue

    def stop(self):
        self._stop_event.set()
        self.join()

servant:实现实际逻辑(例如,计算方法)。

import time


class servant:
    def compute(self, x, y):
        time.sleep(2)
        return x + y

proxy:将方法调用转换为请求并返回结果的 future。

from concurrent.futures import future


class proxy:
    def __init__(self, servant, scheduler):
        self.servant = servant
        self.scheduler = scheduler

    def compute(self, x, y):
        future = future()
        request = methodrequest(self.servant.compute, (x, y), {}, future)
        self.scheduler.enqueue(request)
        return future

客户端:异步提交任务并在需要时检索结果。

def main():
    # Initialize components
    scheduler = Scheduler()
    scheduler.start()

    servant = Servant()
    proxy = Proxy(servant, scheduler)

    # Client makes an asynchronous call
    print("Submitting tasks...")
    future1 = proxy.compute(5, 10)
    future2 = proxy.compute(15, 20)

    # Perform other tasks while computation is ongoing
    print("Doing other work...")

    # Retrieve results
    print("Result 1:", future1.result())
    print("Result 2:", future2.result())

    # Shutdown scheduler
    scheduler.stop()

if __name__ == "__main__":
    main()
优点
  • 解耦接口:客户端可以调用方法而无需担心执行细节。
  • 响应性:异步执行确保客户端保持响应。
  • 可扩展性:支持多个并发请求。
缺点
  • 复杂性:增加架构复杂性。
  • 开销:需要额外的资源来管理线程和队列。
  • 延迟:异步处理可能会引入额外的延迟。
结论

主动对象模式是用于管理多线程环境中的异步操作的强大工具。通过将方法调用与执行分离,它可以确保更好的响应能力、可扩展性和更干净的代码库。虽然它具有一定的复杂性和潜在的性能开销,但它的好处使其成为需要高并发和可预测执行的场景的绝佳选择。然而,它的使用取决于当前的具体问题。与大多数模式和算法一样,不存在一刀切的解决方案。

参考

维基百科 - 活动对象

以上就是并发模式:主动对象的详细内容,更多请关注知识资源分享宝库其它相关文章!

版权声明

本站内容来源于互联网搬运,
仅限用于小范围内传播学习,请在下载后24小时内删除,
如果有侵权内容、不妥之处,请第一时间联系我们删除。敬请谅解!
E-mail:dpw1001@163.com

分享:

扫一扫在手机阅读、分享本文

发表评论
热门文章
  • 华为 Mate 70 性能重回第一梯队 iPhone 16 最后一块遮羞布被掀

    华为 Mate 70 性能重回第一梯队 iPhone 16 最后一块遮羞布被掀
    华为 mate 70 或将首发麒麟新款处理器,并将此前有博主爆料其性能跑分将突破110万,这意味着 mate 70 性能将重新夺回第一梯队。也因此,苹果 iphone 16 唯一能有一战之力的性能,也要被 mate 70 拉近不少了。 据悉,华为 Mate 70 性能会大幅提升,并且销量相比 Mate 60 预计增长40% - 50%,且备货充足。如果 iPhone 16 发售日期与 Mate 70 重合,销量很可能被瞬间抢购。 不过,iPhone 16 还有一个阵地暂时难...
  • 酷凛 ID-COOLING 推出霜界 240/360 一体水冷散热器,239/279 元

    酷凛 ID-COOLING 推出霜界 240/360 一体水冷散热器,239/279 元
    本站 5 月 16 日消息,酷凛 id-cooling 近日推出霜界 240/360 一体式水冷散热器,采用黑色无光低调设计,分别定价 239/279 元。 本站整理霜界 240/360 散热器规格如下: 酷凛宣称这两款水冷散热器搭载“自研新 V7 水泵”,采用三相六极马达和改进的铜底方案,缩短了水流路径,相较上代水泵进一步提升解热能力。 霜界 240/360 散热器的水泵为定速 2800 RPM 设计,噪声 28db (A)。 两款一体式水冷散热器采用 27mm 厚冷排,...
  • 惠普新款战 99 笔记本 5 月 20 日开售:酷睿 Ultra / 锐龙 8040,4999 元起

    惠普新款战 99 笔记本 5 月 20 日开售:酷睿 Ultra / 锐龙 8040,4999 元起
    本站 5 月 14 日消息,继上线官网后,新款惠普战 99 商用笔记本现已上架,搭载酷睿 ultra / 锐龙 8040处理器,最高可选英伟达rtx 3000 ada 独立显卡,售价 4999 元起。 战 99 锐龙版 R7-8845HS / 16GB / 1TB:4999 元 R7-8845HS / 32GB / 1TB:5299 元 R7-8845HS / RTX 4050 / 32GB / 1TB:7299 元 R7 Pro-8845HS / RTX 2000 Ada...
  • python怎么调用其他文件函数

    python怎么调用其他文件函数
    在 python 中调用其他文件中的函数,有两种方式:1. 使用 import 语句导入模块,然后调用 [模块名].[函数名]();2. 使用 from ... import 语句从模块导入特定函数,然后调用 [函数名]()。 如何在 Python 中调用其他文件中的函数 在 Python 中,您可以通过以下两种方式调用其他文件中的函数: 1. 使用 import 语句 优点:简单且易于使用。 缺点:会将整个模块导入到当前作用域中,可能会导致命名空间混乱。 步骤:...
  • python中def什么意思

    python中def什么意思
    python 中,def 关键字用于定义函数,这些函数是代码块,执行特定任务。函数语法为 def (参数列表)。函数可以通过其名字和圆括号调用。函数可以接受参数作为输入,并在函数体中使用参数名访问。函数可以使用 return 语句返回一个值,它将成为函数调用的结果。 Python 中 def 关键字 在 Python 中,def 关键字用于定义函数。函数是代码块,旨在执行特定任务。 语法 def 函数定义的语法如下: def (参数列表): # 函数体 示例 定义...