异步队列 - 仅处理最后一条消息

时间:2012-06-19 09:04:42

标签: java asynchronous queue

public void updatePrice(Price update){
   sendPriceUpdate(update); //takes a long time
}

我想构建一个将执行上述操作的类,除非sendPriceUpdate调用仍在运行时,它将等待并排队挂起的更新。一旦呼叫返回,它将发送最后一次更新(并丢弃其他更新)。即等待发送呼叫返回,然后发送最后的待定价格更新。

什么是适当的数据结构?

2 个答案:

答案 0 :(得分:0)

最好的解决方案是更新已经知道这一点并且只获得“增量”数据,即已更改的数据或仅有差异的数据。如果这是不可能的,那么您别无选择,只能回滚最新更新。为此,您需要存储以前的更新,以便您可以撤消它并推送新的更新。这样的事情应该有效:

public class Updater
{
    private static Price prevUpdate = null;

    public static synchronized void updatePrice(Price update)
    {
        if (prevUpdate != null)
        {
            rollbackUpdate(prevUpdate);
        }
        sendPriceUpdate(update); //takes a long time        
        prevUpdate = update;
    }
}

我已将其更改为static,因为我认为您不需要实例化此类的对象。对我来说看起来像静态服务。如果我错了(例如,不同的线程想要使用不同的更新程序,从而跟踪不同的更新),请更改它。

这是线程安全的,但是如果sendPriceUpdate()需要很长时间,它可以锁定updatePrice()方法上的很多线程。此外,这不会考虑抛出任何异常,您应该考虑到这一点。

正如我在评论中所说,恕我直言,这是一个(非常?)糟糕的解决方案,但如果您不知道哪个是最后一个或者最后一个到达时它是唯一的解决方案。软件重新设计可以解决这种情况,或者在更高级别(在调用updatePrice()之前)

之前解决它

答案 1 :(得分:0)

我建议您使用Active-Object模式 - 您应该将队列(AKA激活队列或操作队列)与您的对象相关联。我将首先解释如何解决而不丢弃,然后解释我认为应该如何处理丢弃。 主要思想如下:
A.您的对象将具有队列的字段 - 假设一般类型的队列(具有PriceOperation的通用参数)

B. PriceOperation将持有一个方法对象(java.lang.reflect.method),用于调用-let的PriceManager(具有updatePrice方法)的目标对象,以及参数(让我们说更新它应该是Price)

C. sendPriceUpdate将排队和PriceOperation的对象,方法对象为“更新”(假设Price有这样的方法),或者在同步调用的情况下激活的方法

D.与对象关联的线程将在队列上等待,当队列不为空时,它将使PriceOperation对象出列,并在目标对象上调用该方法(无论是PriceManager还是其他)相关参数(Price对象)

E.这样,您就可以保留待处理更新的队列,并且仍然与您的PriceManager异步工作

F.我刚刚注意到你有兴趣丢弃最后的更新 - 如果是这种情况,那么你应该使用优先级队列,而不是队列,并基于时间戳的优先级排序,以这种方式使PriceOperation最近创建的将被处理。您需要在程序员(PriceManager)和使用者(线程)之间同步此队列。