Scala-futuros y concurrencia
concurrency promise (2)
Estoy tratando de entender los futuros de Scala provenientes de Java: entiendo que puedes escribir:
val f = Future { ... }
entonces tengo dos preguntas:
- ¿Cómo está programado este futuro? ¿Automáticamente?
- ¿Qué programador usará? En Java usaría un ejecutor que podría ser un grupo de subprocesos, etc.
Además, ¿cómo puedo lograr un scheduledFuture
, el que se ejecuta después de un retraso de tiempo específico? Gracias
El bloque Future { ... }
es azúcar sintáctico para una llamada a Future.apply
(como estoy seguro que conoces a Maciej), pasando el bloque de código como primer argumento.
Mirando los documentos para este método , puede ver que toma un ExecutionContext
implícito, y es este contexto el que determina cómo se ejecutará. Por lo tanto, para responder a su segunda pregunta, el futuro se ejecutará según el ExecutionContext en el ámbito implícito (y, por supuesto, si esto es ambiguo, se trata de un error en tiempo de compilación).
En muchos casos, este será el de import ExecutionContext.Implicits.global
, que puede ser modificado por las propiedades del sistema, pero de forma predeterminada utiliza un ThreadPoolExecutor
con un hilo por núcleo del procesador.
La programación, sin embargo, es una cuestión diferente. Para algunos casos de uso, podría proporcionar su propio ExecutionContext
que siempre aplicaba el mismo retraso antes de la ejecución. Pero si desea que la demora sea controlable desde el sitio de llamadas, entonces, por supuesto, no puede usar Future.apply
ya que no hay parámetros para comunicar cómo debe programarse. Sugeriría enviar tareas directamente a un ejecutor programado en este caso.
La respuesta de Andrzej ya cubre la mayor parte del terreno en su pregunta. Vale la pena mencionar que el contexto de ejecución implícita "predeterminada" de Scala ( import scala.concurrent.ExecutionContext.Implicits._
) es literalmente un java.util.concurrent.Executor
, y todo el concepto ExecutionContext es un envoltorio muy delgado, pero está estrechamente alineado con Marco ejecutor de Java.
Para lograr algo similar a los futuros programados, como señala Mauricio, tendrá que usar promesas y cualquier mecanismo de programación de terceros.
No tener compasión por un mecanismo común para esto integrado en el futuro de Scala 2.10 es una lástima, pero nada fatal.
Una promesa es un mango para un cálculo asincrónico. Usted crea uno (asumiendo ExecutionContext
en el alcance) llamando val p = Promise[Int]()
. Acabamos de prometer un número entero.
Los clientes pueden atrapar un futuro que depende de que la promesa se cumpla, simplemente llamando a p.future
, que es solo un futuro de Scala.
Cumplir una promesa es simplemente una cuestión de llamado p.successful(3)
, en cuyo punto se completará el futuro.
Play 2.x resuelve la programación mediante el uso de promesas y un antiguo Java 1.4 Timer.
Aquí hay un enlace a prueba de enlaces a la fuente.
Echemos un vistazo a la fuente aquí:
object Promise {
private val timer = new java.util.Timer()
def timeout[A](message: => A, duration: Long, unit: TimeUnit = TimeUnit.MILLISECONDS)
(implicit ec: ExecutionContext): Future[A] = {
val p = Promise[A]()
timer.schedule(new java.util.TimerTask {
def run() {
p.completeWith(Future(message)(ec))
}
}, unit.toMillis(duration))
p.future
}
}
Esto puede usarse así:
val future3 = Promise.timeout(3, 10000) // will complete after 10 seconds
Tenga en cuenta que esto es mucho mejor que conectar un Thread.sleep(10000)
en su código, lo que bloqueará su hilo y forzará un cambio de contexto.
También vale la pena notar en este ejemplo que val p = Promise...
al comienzo de la función, y el p.future
al final. Este es un patrón común cuando se trabaja con promesas. Supongamos que esta función es prometedora para el cliente y da inicio a un cálculo asincrónico para cumplirla.
Mire aquí para obtener más información acerca de las promesas de Scala. Observe que usan un método future
minúsculas del objeto de paquete concurrent
lugar de Future.apply
. El primero simplemente delega a este último. Personalmente, prefiero el future
minúsculas.