【问题标题】:Scala actors thread controlScala 演员线程控制
【发布时间】:2010-09-06 04:55:51
【问题描述】:

我想更多地了解控制每个 Scala 角色运行位置的可能性。我碰巧遇到了一个特殊的情况:需要高反应性,代码的很大一部分是时间关键的,最糟糕的是,我在 Android 上。考虑到这一点,我的主要目标是:使代码尽可能地可读和简单。

我理想中想要达到的目标(其中一些听起来不合理/完全愚蠢,请阅读下面的基本原理)
- 我希望能够在某个特定的、始终相同的任意线程中响应一些消息,但我不需要阻止它等待消息。
- 我希望我的大部分处理都在一个工作线程池上完成,理想情况下可以在 Scala 演员支持的情况下自动调整大小,同时保证这个处理永远不会发生在上面的任意线程上。

这些要求源于 Android 的必要性:Android 框架使用一个特殊的线程来触摸 UI,如果您从另一个线程触摸任何 UI 对象,则会出现异常。通过这种方式,它强制执行某种线程/锁模型,这正是我想要解决的问题。但无论如何,事情就是这样:我必须确保我的一些处理,即处理 UI 对象的内容,在这个线程上运行,而不是在其他线程上运行,因为框架令人讨厌地说我应该这样做。 一个恼人的副作用是,只要这个线程正在处理我的代码,UI 就会停止更新并且我的应用程序停止响应。所以我需要确保这个线程不会被随机选择用于我可以在某些 react{} 中拥有的长时间运行的代码,并且理想情况下它永远不会处理可能由另一个线程完成的事情。

android 框架提供了一个名为 Handle 的类,它实现了某种消息传递——你给它发送一个 Runnable,它就会在 UI 线程上运行。如果需要,我可以使用它。每次都创建一个 Runnable 会使代码严重混乱 - 可以做的一件事是将其封装在某种方法中,以便我可以编写类似
onUIThread { /* 一些代码 */ }
...这比 new Runnable() { def run () {}} 要好得多。另一方面,这基本上就是 onUIThread 函数要做的事情,所以我将创建两个闭包——然后我必须处理闭包的内存分配细节。我必须这样做,因为每次我分配一个对象时,GC 都有机会运行,并且在 Android 上执行通常会暂停 150 毫秒,如果它发生在关键执行路径中,这将破坏我的用户体验。

最后:
- 我有什么方法可以将actor与线程静态关联,这样我就可以拥有一个UIactor,在其中做出react{},并始终让它的代码在UI线程上运行? /* 我知道它本身就是一个糟糕的设计,请阅读上面的理由,看看为什么我忍不住 */
- 我有什么方法可以确保永远不会考虑使用这个特定线程来响应 react{} 中的消息? - 考虑到我的限制,我可以做些什么来获得更好的代码易读性,有什么建议吗?

【问题讨论】:

    标签: android scala actor


    【解决方案1】:

    您可以通过扩展将任务推送到 ui 线程的 IScheduler 特征来实现客户调度程序,然后覆盖需要在 ui 线程上运行的 Actor 上的调度程序方法。

    不久前有人用 Swing 尝试过这个,我认为它有效: http://scala-programming-language.1934581.n4.nabble.com/scala-Swing-event-thread-actors-td1987246.html

    然后让其他actor使用正常的调度器。

    但我要指出,react {} 会导致创建一个最终被包裹在一个可运行文件中的闭包。它还使用异常进行流控制,这会引入相当大的开销(我不知道在 Dalvik 上有多少)。因此,如果 GC 闭包真的会损害您的应用程序的性能,我怀疑演员是否会拯救您。

    【讨论】:

    • 这听起来正是我所需要的。非常感谢,我会调查的!关于闭包,这仅意味着我必须小心,在执行关键代码时不要为它们分配内存,因为这会触发(暂定)GC,即使它没有什么可清理的,也会破坏我的性能。但如果我自己创建 Runnables 也是一样,所以……没有免费的午餐。无论如何,非常感谢你的好答案!
    猜你喜欢
    • 1970-01-01
    • 2010-10-07
    • 2011-01-20
    • 2011-01-30
    • 2014-06-29
    • 2019-04-23
    • 2011-02-14
    • 2010-12-04
    • 2011-02-20
    相关资源
    最近更新 更多