代码之家  ›  专栏  ›  技术社区  ›  N. Kudryavtsev

当Kotlin通道满时执行一段代码

  •  1
  • N. Kudryavtsev  · 技术社区  · 7 年前

    我想编写一个简单的批处理程序类。它有一个请求队列,等待该队列变满或等待一段时间,然后才与数据库对话。

    通过通道实现此队列非常方便,这样我们的客户机将在队列满时挂起。但我如何才能知道频道是否已满?

    当然,我可以创建一个方法,将某些内容发送到通道,然后执行一些检查。下一步是将其封装在从Channel派生的类中。仍然很脏(不清楚我该如何处理 onSend / onReceive ). 还有其他优雅的解决方案吗?也许是盒子里的东西?

    2 回复  |  直到 5 年前
        1
  •  6
  •   Roman Elizarov    7 年前

    这并不是现成的,但相应的批处理逻辑可以使用actor轻松实现。您并不需要一个类来实现这一点(但如果愿意,可以将此代码封装在一个类中)。您可以使用以下实现作为模板:

    const val MAX_SIZE = 100 // max number of data items in batch
    const val MAX_TIME = 1000 // max time (in ms) to wait
    
    val batchActor = actor<Data> {
        val batch = mutableListOf<Data>()
        var deadline = 0L // deadline for sending this batch to DB
        while (true) {
            // when deadline is reached or size is exceeded, then force batch to DB
            val remainingTime = deadline - System.currentTimeMillis()
            if (batch.isNotEmpty() && remainingTime <= 0 || batch.size >= MAX_SIZE) {
                saveToDB(batch)
                batch.clear()
                continue
            }
            // wait until items is received or timeout reached
            select<Unit> {
                // when received -> add to batch
                channel.onReceive {
                    batch.add(it)
                    // init deadline on first item added to batch
                    if (batch.size == 1) deadline = System.currentTimeMillis() + MAX_TIME
                }
                // when timeout is reached just finish select, note: no timeout when batch is empty
                if (batch.isNotEmpty()) onTimeout(remainingTime) {}
            }
        }
    }
    

    现在你就这么做 batchActor.send(data) 当您需要向数据库发送任何内容时,actor内部的逻辑负责批处理并将结果批保存到数据库中。

        2
  •  0
  •   hexkid    7 年前

    通道接口声明了一个isFull属性,可以查询该属性以确定其是否已达到容量。

    我看不出是否有回调函数在达到容量时自动调用函数,但您可以定期检查此isFull属性以查看它是否达到容量。