Эту задачу очень трудно выполнить эффективно, надежно и безопасно с помощью Scala стандартной библиотеки Futures. Нет способа прервать Future
, который еще не завершен, а это означает, что даже если вы решите игнорировать его результат, он все равно будет продолжать работать и тратить впустую память и процессорное время. И даже если был способ прервать выполнение Future
, нет способа гарантировать, что выделенные ресурсы (сетевые подключения, открытые файлы и т. Д. c.) Будут правильно освобождены.
I хотел бы отметить, что в реализации, данной Иваном Станиславчу c, есть ошибка: если main
Future не удастся, то обещание никогда не будет выполнено, что вряд ли будет тем, что вы хотите.
Поэтому я настоятельно рекомендую изучить современные системы одновременных эффектов, такие как ZIO или кошачий эффект. Это не только безопаснее и быстрее, но и намного проще. Вот реализация с ZIO, у которой нет этой ошибки:
import zio.{Exit, Task}
import Function.tupled
def completeOnMain[A, B](
main: Task[A], secondary: Task[B]): Task[(A, Exit[Throwable, B])] =
(main.forkManaged zip secondary.forkManaged).use {
tupled(_.join zip _.interrupt)
}
Exit
- это тип, описывающий, как завершилась задача secondary
, то есть путем успешного возврата B
или из-за ошибка (типа Throwable
) или из-за прерывания.
Обратите внимание, что этой функции можно дать гораздо более сложную подпись, которая расскажет вам намного больше о том, что происходит, но я хотел бы упростить ее здесь .