使用 Akka 进行 Scala 折叠

Posted

技术标签:

【中文标题】使用 Akka 进行 Scala 折叠【英文标题】:Scala folding using Akka 【发布时间】:2011-09-19 11:52:01 【问题描述】:

我在 Java 中实现了我所谓的“可折叠队列”,即 ExecutorService 使用的 LinkedBlockingQueue。这个想法是每个任务作为一个唯一的 id,如果在队列中,而另一个任务通过相同的 id 提交,它不会被添加到队列中。 Java 代码如下所示:

public final class FoldablePricingQueue extends LinkedBlockingQueue<Runnable> 
    @Override
    public boolean offer(final Runnable runnable) 
        if (contains(runnable)) 
            return true; // rejected, but true not to throw an exception
         else 
            return super.offer(runnable);
        
    

线程必须预先启动,但这是一个小细节。我有一个实现 Runnable 的抽象类,它需要一个唯一的 id ......这是传入的那个

我想使用 Scala 和 Akka(Actor)实现相同的逻辑。 我需要访问邮箱,我想我需要覆盖!方法并检查事件的邮箱..以前有人这样做过吗?

【问题讨论】:

在我刚刚发布此内容时阅读此内容:***.com/questions/2721337/… 【参考方案1】:

正是 Akka 邮箱的工作原理。 Akka 邮箱在任务队列中只能存在一次。

看看:

https://github.com/jboner/akka/blob/master/akka-actor/src/main/scala/akka/dispatch/Dispatcher.scala#L143

https://github.com/jboner/akka/blob/master/akka-actor/src/main/scala/akka/dispatch/Dispatcher.scala#L198

使用原子布尔值非常便宜地实现,因此无需遍历队列。

另外,顺便说一下,Java 中的 Queue 已损坏,因为它没有覆盖 put、add 或 offer(E, long, TimeUnit)。

【讨论】:

抱歉,您误解了我的问题。我不是在询问每个 Q 的 MB 实例数,而是更多关于接受任务到 MB 中(如果它们已经在 MB 中) 最简单的可能只是为您的调度员创建自己的邮箱实现。看看它是怎么做的,直接重写入队方法 覆盖您的调度程序的 createMailbox 方法以返回一个执行重复数据删除的邮箱,检查 Akka 1.2) 的 ExecutorBasedEventDrivenDispatcher.scala 的源代码,它显示了如何覆盖 createMailbox 以创建自定义类型的邮箱。跨度> 【参考方案2】:

也许你可以用两个演员来做到这一点。一个facade 一个和一个worker 一个。客户将作业发送至facadeFacade 然后转发到 worker,并在其内部状态中记住它们,一个 Set queuedJobs。当它收到queued 的作业时,它会丢弃它。每次worker 开始处理一个作业(或完成它,无论哪个适合你),它都会向 Facade 发送一条 StartingOn(job) 消息,这会将其从 queuedJobs 中删除。

【讨论】:

是的,有很多方法可以做到这一点 - 但看看非常简单的 Java 版本,我期望使用 Akka 更简单的方法来做到这一点。可能需要添加的正确问题是:我是否可以通过定义明确的 API 访问邮箱? @JTS:我不认为你可以。顺便说一句,didierd 解决方案非常简单,我确信实现的代码不会比您展示的 Java 解决方案长。为了简化任务,您可以例如使用forward,它可以通过保留发件人来轻松转发。 groups.google.com/group/akka-user/browse_thread/thread/…【参考方案3】:

建议的设计没有意义。最接近Runnable 的是Actor。当然,您可以将它们保存在列表中,如果它们已经存在,则不要添加它们。此类列表由 routing actors 保存,可以从 Akka 提供的现成部分创建,也可以使用 forward 方法从基本参与者创建。

你不能查看其他演员的邮箱,覆盖! 没有任何意义。您所做的是将所有消息发送到路由参与者,然后该路由参与者将它们转发到正确的目的地。

自然,由于它接收这些消息,它可以在那时执行任何逻辑。

【讨论】:

我同意。看起来是最好的选择。会试一试的。

以上是关于使用 Akka 进行 Scala 折叠的主要内容,如果未能解决你的问题,请参考以下文章

斯卡拉:折叠与折叠左

为啥折叠推断任何?

scala 数据结构:折叠扫描拉链(合并)迭代器

如何将折叠左侧运算符“:/”转换为scala中的foldLeft函数?

如何折叠Scala迭代器并获得延迟计算的序列作为结果?

团购快结束保温杯,折叠浴桶,湿巾,scala清洁用品