Завершение будущего с TimeoutException или Awaiting? - PullRequest
0 голосов
/ 14 мая 2018

У меня есть следующая черта:

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

Ответы [ 2 ]

0 голосов
/ 14 мая 2018

Эти две черты имеют различное поведение, поэтому оно немного зависит от того, чего вы пытаетесь достичь.

Черта I. говорит

Напишите некоторые данные и занимайте столько времени, сколько необходимо.Завершите Future, когда запись завершится или не удастся.

Черта II. говорит

Попробуйте написать несколькоданные, но сдавайтесь, если это займет слишком много времени.Завершите Future, когда запись завершится, или произойдет сбой, или по истечению времени ожидания

Второй вариант предпочтителен, потому что он гарантированно прогрессирует, и потому что write не остается висеть, если Await.result раз.

0 голосов
/ 14 мая 2018

Вариант II, как правило, предпочтителен (или глобально установленный тайм-аут), потому что фьючерсы обычно не "ожидаются", но вместо этого имеют тенденцию к цепочке.

Необычно писать код, подобный:

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

и более обычно писать код как:

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