2

我有一个解析器,在为一行收集数据之后,我想触发一个 aync 函数并让它处理该行,而主线程继续运行并获取下一行。

我看过这篇文章:如何在 Groovy 中同时执行两个任务并等待结果?但我不确定这是适合我情况的最佳解决方案。

我想要做的是,在读取所有行之后,等待所有异步函数完成,然后再继续。使用 Promise 集合的一个问题是列表可能很大(100,000+)。

另外,我想在我们进行时报告状态。最后,我不确定是否要自动等待超时(例如在 get() 上),因为文件可能很大,但是,我确实希望允许用户出于各种原因终止该进程。

所以我现在所做的是记录解析的行数(因为它们通过rowsRead发生),然后使用来自 Promise 的回调来记录正在完成处理的另一行,如下所示:

def promise = processRow(row)
promise.whenBound {
    rowsProcessed.incrementAndGet()
}

其中rowsProcessed是一个 AtomicInteger。

然后在工作表末尾调用的代码中,在完成所有解析并且我正在等待处理完成之后,我正在这样做:

boolean test = true
while (test) {
    Thread.sleep(1000)  // No need to pound the CPU with this check
    println "read: ${sheet.rowsRead}, processed: ${sheet.rowsProcessed.get()}"
    if (sheet.rowsProcessed.get() == sheet.rowsRead) {
        test = false
    }
}

好消息是,我这里没有 Promise 对象的爆炸 - 只是一个简单的计数来检查。但我不确定经常睡觉是否与检查每个 Promise() 对象上的 get() 一样有效。

所以,我的问题是:

  1. 如果我改用 Promises 的集合,如果执行上述 while 循环的线程被 Thread.interrupt() 中断,get() 会做出反应并返回吗?
  2. 使用 Promises 集合并在每个上调用 get() 会比尝试睡眠并经常检查更有效吗?
  3. 有没有我没有考虑过的另一种更好的方法?

谢谢!

4

2 回答 2

3
  1. 如果等待(主)线程被中断,调用 allPromises*.get() 将抛出 InterruptedException
  2. 是的,无论如何都已经创建了承诺,因此在我看来,将它们分组到一个列表中不应强加额外的内存要求。
  3. 使用 CountDownLanch 或 Phaser 的建议解决方案比使用忙等待更适合 IMO。
于 2012-11-16T10:35:06.143 回答
2

a的替代方法AtomicInteger是使用 a CountDownLatch。它避免了对象sleep的大集合Promise。你可以像这样使用它:

latch = new CountDownLatch(sheet.rowsRead)
...
def promise = processRow(row)
promise.whenBound {
    latch.countDown()
}
...
while (!latch.await(1, TimeUnit.SECONDS)) {
    println "read: ${sheet.rowsRead}, processed: ${sheet.rowsRead - latch.count}"
}
于 2012-11-15T21:19:39.177 回答