我正在编写一个多线程桌面应用程序。
我不确定多线程对架构的影响。有很多关于架构的文献,但我知道没有考虑多线程的文献。关于多线程(互斥,信号量等)的低级别的东西有很多文献,但我知道没有描述这些概念是如何嵌入到架构中的。
您建议哪些文献填补这一空白?
我的申请包括
Presentation
使用GUI工具包创建和管理对话框,Kernel
知道应用程序域的所有内容,Controller
知道Kernel
和Presentation
以及这两者之间的温和情况。更确切地说,这是文件的打开方式:
Presentation
表示FileOpenCommand
。ApplicationController
收到此信号并且
ApplicationKernel
创建File
对象ApplicationPresentation
创建FilePresentation
对象FileController
对象,将File
和FilePresentation
传递给构造函数。FileController
在其File
和FilePresentation
上注册为观察者。假设File
提供了一个不应阻止用户界面的长时间运行操作Init()
。我想到了两种方法:
File::Init()
返回一个封装线程的对象,可以用来注册一个被通知进度,错误,完成等的观察者。这会给FileController
带来很多责任。是观察者),因为现在可以从主线程和工作线程访问它。Controller
中的工作线程。 File::Init()
将不返回任何内容,但ApplicationKernel
将表示主线程中长时间运行操作的创建,进度和错误。这将通过ApplicationKernel
拖动大量通信,将其变成类似神对象的东西。这两个中的哪一个是桌面应用程序中多线程的常用方法(如果有的话)?您推荐哪种替代方法?
答案 0 :(得分:3)
我建议您考虑使用actor model。它是一种并发抽象,隐藏了许多与线程,锁等相关的细节。
修改强>
@ CMR的评论刺激了一些额外的评论......
在演员模型下,我想应用仍然会使用问题中建议的相同组件进行结构化:Presentation
,ApplicationController
等。与演员模型的区别在于组件(现在为actor)不会直接引用彼此。相反,他们会保留可以向其发送异步,不可变消息的频道。
“打开文件”情况下的事件序列在actor模型中基本相同,除了在步骤2.3中将通道传递给FileController
而不是直接对象引用。同样,观察员注册通过渠道进行。
那有什么区别?主要区别在于没有代码需要是线程感知的。线程对应用程序逻辑是不可见的,是actor框架的关注点。如果人们可以遵循仅通过通道传递不可变对象的规则(某些actor框架强制执行),那么几乎所有与线程同步相关的困难逻辑都会消失。当然,必须将思维模式从同步编程模型转换为异步编程模型 - 不一定是一项微不足道的任务。但是,我认为,不必考虑线程安全性(至少在某些复杂系统中)的好处超过了该开关的成本。
特别是在UI编程中,异步模型可以更轻松地提供良好的用户反馈。例如,UI元素可以启动长时间运行的任务,显示“工作...”消息,然后进入睡眠状态。一段时间之后,消息到达,传递长时间运行的任务的结果,UI元素随后显示该结果而不是“工作...”消息。以类似的方式,当每个树节点的数据到达传入消息时,可以递增地构建树视图。
您可以将演员模型视为经典UI“事件泵”方法的概括 - 除了每个组件(演员)同时运行自己的事件泵而不是一个泵调度到一堆组件。 Actor框架提供了一种以非常低的开销运行大型甚至大量此类“同步泵”的方法。特别是,少量线程(比如每个cpu一个)服务于大量的actor。