使用 TimeoutException 或 Awaiting 完成未来?

Completing future with TimeoutException or Awaiting?

我有以下特点:

trait Tr{
     /**
      * Returns future of the number of bytes written
      */
     def write(bytes: Array[Byte]): Future[Long]
}

所以我可以这样等待结果:

我.

val bts: Array[Byte] = //...
val to: Long = //...
val tr: Tr = //...
Await.result(tr.write(bts), to)

但我也可以用有点不同的方式设计 Tr

trait Tr{
     /**
      * Returns future of the number of bytes written
      */
     def write(bytes: Array[Byte], timeout: Long): Future[Long]
}

II.

val bts: Array[Byte] = //...
val to: Long = //...
val tr: Tr = //...
Await.result(tr.write(bts, to), Duration.Inf)

更好的方法是什么?我认为 II 案例在实际写入 IO 不可中断或由调用者线程执行的情况下有用。因此,为了灵活性,我会以 II 方式设计线程。

东西在II中永远写着,看起来有点奇怪。

这样做对吗?或者我在滥用 Future?

更新:考虑以下可能的 Tr 实现:

class SameThreadExecutionContext extends ExecutionContext{
  override def execute(runnable: Runnable): Unit = runnable.run()
  override def reportFailure(cause: Throwable): Unit = ???
}

clas DummyTrImpl extends Tr{
    private final implicit val ec = new SameThreadExecutionContext
    override def write(bytes: Array[Byte]): Future[Long] = {
         Thread.sleep(10000)
         throw new RuntimeException("failed")
    }
}

现在如果我这样写:

val bts: Array[Byte] = //...
val to: Long = 1000
val tr: Tr = new DummyTrImpl
Await.result(tr.write(bts), to) //Waiting 10 secs instead of 1 
                                //and throwing RuntimeException instead of timeout

选项 II 通常是首选(或全局设置超时),因为 Futures 通常不是 "awaited",而是倾向于链接起来。

写这样的代码是不寻常的:

Await.result(tr.write(bts, to))

更常见的是写这样的代码:

tr.write(bts, to).then(written => ... /* write succeeded, do next action */ ..)

这两个特征有不同的行为,因此这在一定程度上取决于您要实现的目标。

特质I.

Write some data and take as long as necessary. Complete the Future when the write completes or fails.

特质II.

Try to write some data but give up if it takes too long. Complete the Future when the write completes, or fails, or times out

首选第二个选项,因为它可以保证继续进行,而且如果 Await.result 超时,write 不会被挂起。