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