У меня есть следующая черта:
trait Tr{
/**
* Returns future of the number of bytes written
*/
def write(bytes: Array[Byte]): Future[Long]
}
Таким образом, я могу ждать результата следующим образом:
I.
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 имеет свое применение в случае, когда фактический ввод-вывод не прерывается или выполняется потоком вызывающей стороны.Так что для гибкости я бы разработал нить II .
Вещи пишутся вечно в II выглядит немного странно.
Правильно ли это?Или я злоупотребляю Future
?
Upd: рассмотрим следующую возможную реализацию 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