El patrón de diseño de objetos activos desacopla la ejecución de métodos de la invocación de métodos para objetos que residen cada uno en su propio hilo de control. [1] El objetivo es introducir concurrencia , mediante el uso de invocación de métodos asincrónicos y un programador para gestionar solicitudes. [2]
El patrón consta de seis elementos: [3]
Un ejemplo de patrón de objeto activo en Java . [4]
En primer lugar, podemos ver una clase estándar que proporciona dos métodos que establecen un valor de un valor doble. Esta clase NO se ajusta al patrón de objeto activo.
clase MiClase { privado doble val = 0.0 ; void doSomething () { val = 1.0 ; } vacío hacerAlgoMás () { val = 2.0 ; } }
La clase es peligrosa en un escenario de subprocesamiento múltiple porque ambos métodos pueden ser llamados simultáneamente, por lo que el valor de val (que no es atómico, se actualiza en múltiples pasos) podría ser indefinido, una condición de carrera clásica. Por supuesto, puede usar la sincronización para resolver este problema, lo que en este caso trivial es fácil. Pero una vez que la clase se vuelve realmente compleja, la sincronización puede volverse muy difícil. [5]
Para reescribir esta clase como un objeto activo, puedes hacer lo siguiente:
clase MyActiveObject { privado doble val = 0.0 ; privado BlockingQueue < Runnable > dispatchQueue = nuevo LinkedBlockingQueue < Runnable > (); public MyActiveObject () { new Thread ( new Runnable () { @Override public void run () { try { while ( true ) { dispatchQueue.take (). run (); } } catch ( InterruptedExceptione ) { // ok, simplemente termina el despachador } } } ) . start ( ); } void doSomething () lanza InterruptedException { dispatchQueue.put ( new Runnable () { @Override public void run ( ) { val = 1.0 ; } } ) ; } void doSomethingElse () lanza InterruptedException { dispatchQueue.put ( new Runnable () { @Override public void run ( ) { val = 2.0 ; } } ) ; } }
Otro ejemplo de patrón de objeto activo en Java implementado en Java 8 proporciona una solución más corta.
public class MyClass { private double val ; // contenedor para tareas // decide qué solicitud ejecutar a continuación // asyncMode=true significa que nuestro hilo de trabajo procesa su cola de tareas local en orden FIFO // solo un hilo puede modificar el estado interno private final ForkJoinPool fj = new ForkJoinPool ( 1 , ForkJoinPool.defaultForkJoinWorkerThreadFactory , null , true ); // implementación del método de objeto activo public void doSomething () throws InterruptedException { fj.execute (() -> { val = 1.0 ; }); } // implementación del método de objeto activo public void doSomethingElse ( ) throws InterruptedException { fj.execute ( () -> { val = 2.0 ; } ); } }