我有以下特点:
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
答案 0 :(得分:4)
选项II通常是首选(或全局设置的超时),因为期货通常不会等待#34;但往往会被链接。
编写如下代码是不常见的:
Await.result(tr.write(bts, to))
更常见的是编写代码:
tr.write(bts, to).then(written => ... /* write succeeded, do next action */ ..)
答案 1 :(得分:2)
这两个特征有不同的行为,所以它取决于你想要达到的目标。
特质 我。 说
写一些数据,并根据需要采取。写入完成或失败时完成
Future
。
特质 II。 说
尝试写一些数据,但如果花费太长时间就会放弃。写入完成,失败或超时
时完成Future
第二个选项是首选,因为它可以保证进展,并且如果write
超时,Await.result
不会挂起。