scala concurrency java.util.concurrent

scala.concurrent.blocking-¿qué es lo que realmente hace?



concurrency java.util.concurrent (1)

Pasé un tiempo aprendiendo el tema de los contextos de ejecución de Scala, los modelos de subprocesamiento subyacentes y la concurrencia. ¿Puede explicar de qué forma el scala.concurrent.blocking "ajusta el comportamiento del tiempo de ejecución" y "puede mejorar el rendimiento o evitar interbloqueos" como se describe en el scaladoc ?

En la documentación , se presenta como un medio para esperar la API que no implementa Awaitable. (¿Tal vez también solo el cómputo de ejecución prolongada debería ser envuelto?).

¿Qué es lo que realmente hace?

Seguir a través de la fuente no traiciona fácilmente sus secretos.


blocking está destinado a actuar como una pista al ExecutionContext que el código contenido está bloqueando y podría llevar a la falta de hilo. Esto le dará al grupo de subprocesos la oportunidad de engendrar nuevos hilos para evitar la inanición. Esto es lo que significa "ajustar el comportamiento del tiempo de ejecución" . Sin embargo, no es mágico, y no funcionará con cada ExecutionContext .

Considera este ejemplo:

import scala.concurrent._ val ec = scala.concurrent.ExecutionContext.Implicits.global (0 to 100) foreach { n => Future { println("starting Future: " + n) blocking { Thread.sleep(3000) } println("ending Future: " + n) }(ec) }

Esto está utilizando el ExecutionContext global predeterminado. Al ejecutar el código tal como está, notará que los 100 Future s se ejecutan todos de inmediato, pero si elimina el blocking , solo ejecutan unos pocos a la vez. El ExecutionContext predeterminado reaccionará a las llamadas de bloqueo (marcadas como tales) al generar nuevos hilos, y por lo tanto no se sobrecargará con la ejecución de Future s.

Ahora mira este ejemplo con un grupo fijo de 4 hilos:

import java.util.concurrent.Executors val executorService = Executors.newFixedThreadPool(4) val ec = ExecutionContext.fromExecutorService(executorService) (0 to 100) foreach { n => Future { println("starting Future: " + n) blocking { Thread.sleep(3000) } println("ending Future: " + n) }(ec) }

Este ExecutionContext no está diseñado para procesar nuevos hilos de spawn, por lo que incluso con mi código de bloqueo rodeado de blocking , puede ver que solo se ejecutará a lo sumo 4 Future s a la vez. Y es por eso que decimos que "puede mejorar el rendimiento o evitar bloqueos" : no está garantizado. Como vemos en este último ExecutionContext , no está garantizado en absoluto.

¿Como funciona? Como vinculado, el blocking ejecuta este código:

BlockContext.current.blockOn(body)(scala.concurrent.AwaitPermission)

BlockContext.current recupera el BlockContext del hilo actual, que se ve here . Un BlockContext suele ser solo un Thread con el rasgo de BlockContext mezclado. Como se ve en la fuente, se almacena en un ThreadLocal , o si no se encuentra allí, es un patrón que coincide con el subproceso actual. Si el hilo actual no es un BlockContext , entonces se usa DefaultBlockContext su lugar.

A continuación, se blockOn en el BlockContext actual. blockOn es un método abstracto en BlockContext , por lo que su implementación depende de cómo lo maneje ExecutionContext . Si observamos la implementación de DefaultBlockContext (cuando el hilo actual no es un BlockContext ), vemos que blockOn realidad no hace nada allí. Entonces, usar el blocking en un BlockContext no BlockContext significa que no se hace nada especial, y el código se ejecuta tal como está, sin efectos secundarios.

¿Qué pasa con los hilos que son BlockContext s? Por ejemplo, en el contexto global , visto here , blockOn hace bastante más. ForkJoinPool un ForkJoinPool más, se puede ver que está utilizando ForkJoinPool debajo del capó, con DefaultThreadFactory definido en el mismo fragmento que se utiliza para generar nuevos hilos en ForkJoinPool . Sin la implementación de blockOn desde BlockContext (thread), ForkJoinPool no sabe que está bloqueando, y no tratará de engendrar más hilos en respuesta.

Scala''s Await también usa blocking para su implementación.