por Pablo | Jun 24, 2018
ExecutorService es el nombre que se le ha dado a la API de concurrencia implantada en el JDK7. Su nombre deriva de la única interfaz que hereda de Executor.
Hemos hablado más en profundidad en este blog sobre el patrón Command y hoy venimos a desenmarañar la relación de las clases de esta API para ver una vez más, como el JDK no es ajeno a la implantación de patrones.
Esta API no solo implementa el patrón Command, también usa el Method Factory para devolvernos una instancia. No reflejaremos esto para no complicar más de lo necesario el diagrama UML.
Comencemos por la clase ThreadPoolExecutor. Por supuesto, simplificaremos su explicación, ya que la clase es un pequeño infierno de código usando clases muy variopintas.
Este ThreadPoolExecutor que tomamos como ejemplo, es una de las posibilidades que tenemos a la hora de instanciar un pool de threads de tipo ExecutorService.
Esta clase contiene un atributo de tipo BlockingQueue, que básicamente permite que un hilo introduzca tareas en la cola y otro las consuma de forma segura.
También contiene una inner-class llamada Worker. Esta clase tiene un constructor parametrizado con un Runnable que se encarga de mantener el control de los hilos que ejecutan las tareas. Se podría interpretar como la clase encargada de ejecutar las tareas de la BlockingQueue.
Cuando llamamos al método execute() de la clase principal (recordemos que ThreadPoolExecutor contiene una clase hija Worker), lo que realmente hacemos es comprobar el número de Workers y el máximo que podemos tener para ejecutar la tarea.
- Si tenemos menos Workers de los que podríamos tener, añadimos uno para ejecutar la tarea.
- SI tenemos el máximo numero de Workers ya trabajando, metemos en la blockingQueue esa tarea para ser ejecutada más adelante.
- SI no podemos crear más Workers ni poner en la cola esa tarea, se crea un nuevo hilo solo para desecharla.
A continuación pongo un diagrama UML muy sencillo en el que se aprecian las principales clases, interfaces y relaciones.

¿Veis el parecido con el patrón Command? El invoker aquí esta representado por la clase ThreadPoolExecutor, la cual a través de sus Workers, va resolviendo tareas que el usuario crea.
Recordemos el propósito fundamental del patrón Command: desacoplar la ejecución de la clase que ejecuta una tarea del usuario que la crea, para ser gestionada por un intermediario.
La API Concurrence efectivamente usa el patrón Command, por supuesto de una forma más refinada (ya que usa mecanismos de control de sincronicidad, entre ostras cosas) pero no deja de cumplir con el principio del patrón.
por Pablo | Jun 22, 2018
Una interfaz funcional es un tipo muy concreto de interfaz en Java.
Están disponibles a partir de Java 8 y se definen como las interfaces con un único método abstracto. A partir de Java 8 es posible crear interfaces con métodos default, o dicho de otra forma, métodos con implementación por defecto, por eso es necesario recordar que una interfaz funcional no es una interfaz con un sólo método, sino con un solo método abstracto.
Veamos un ejemplo de una interfaz funcional y su notación.
Puedes preguntarte qué ventajas puede haber en definir una interfaz como funcional, y la respuesta es que ninguna, pero en Java 8, simultáneamente con el lanzamiento de este nuevo tipo de interfaces, surgieron las expresiones lambda, las cuales sí poseen muchas características interesantes.
Las expresiones Lambda
Una expresión lambda es una forma de hacer referencia a métodos anónimos cuando hacemos referencias a clases anónimas. ¿Cómo te has quedado? Esta definición da lugar a mas preguntas que respuestas. ¿Qué son una clase anónima y un método anónimo?
- Una clase anónima es una clase sin un tipo concreto especificado, es decir, una clase que en tiempo de ejecución puede ser cualquier cosa que implemente una determinada interfaz.
- Un método anónimo es el mismo concepto que la clase anónima trasladada a los métodos: el método de una interfaz implementado a un tipo de objeto no especificado. Se llaman anónimas porque no se especifica el nombre del método en la expresión.
¿Cuales son las ventajas de esto?
- Si necesitas momentáneamente una instancia de una clase para algo concreto y no necesitas usarla nunca más, puedes evitar crear una clase específica que ejecute el método que quieres lanzar.
- Cuando la implementación es corta, el que la implementación de la clase se encuentre directamente en el lugar donde se usa, puede hacer que el código sea más legible y entendible.
En este ejemplo hemos creado una clase anónima que implementa la interfaz Runnable. Nos da igual de qué tipo sea la clase que implemente Runnable, solo queremos una excusa para ejecutar el método que define la interfaz.
Pero da la casualidad de que además Runnable es una interfaz funcional que implementa el método run(). Esto quiere decir que podemos usar una expresión lambda para implementar el código del método abstracto sobre una clase anónima.
La sintaxis de una expresión lambda es
Interfaz nombre_exp_lambda = (parámetro_función) -> {cuerpo_función}
Si seguimos el ejemplo de la Interfaz Runnable vemos que el método run() no tiene parámetros, y el código del anterior snippet puede ser simplificado aún más:
Hemos creado una clase anónima que llama al único método abstracto de la interfaz que implementa. Así de sencillo.
Las expresiones lambda pueden usar variables y parámetros siempre que estos sean finales o efectivamente finales. Los elementos efectivamente finales son aquellos que
Al principio puede parecer un poco engorroso, pero en cuanto te acostumbras, encuentras la elegancia de un código escueto, funcional, fácil de leer y en ocasiones propicio para mejoras en el rendimiento
Con esta breve introducción creo que ya puedes comenzar a leer la documentación de Oracle al respecto, donde se analizan otras particularidades de este tipo de programación.
por Pablo | Jun 15, 2018
En la entrada del patrón observer, terminábamos con una pregunta.
¿Cómo podemos controlar cuándo se envían las notificaciones?
La respuesta es simple: añadiendo un estado al sujeto que envía las notificaciones mediante una variable. Si esta variable tiene un valor, notificamos a los observadores y la devolvemos a su estado original. En caso contrario no hacemos nada.
Por ejemplo, supongamos que la clase Balanza notifica a sus observadores cuando se ha puesto un peso sobre ella de más de 1000gr. Si no tuviéramos esa variable booleana en cada pesaje tendríamos que recorrer toda la lista, notificando de cualquier pesaje.
Podrías pensar acertadamente que existe cierta complicación en el código. ¿Por que no notificar directamente si se da una condición a los observadores? Bueno, en este ejemplo quizás si sería lo más lógico, pero sirve como excusa para extrapolar a otras situaciones donde las condiciones para notificar sean más complejas.
Aunque controlar las notificaciones no es algo contemplado en el propio patrón observer, la implementación de Java sí que añade por defecto esta posibilidad. Si echamos un vistazo al código de la clase Observable vemos que tiene dos campos: un Vector de objetos Observer y un atributo booleano.
Una herencia envenenada
Que Observable tenga una clase Vector para albergar los Observer puede ser indicativo de una necesaria huida. Pero aprovechemos que estamos aquí para hacer énfasis en el punto clave de esta implementación:
- Observable es una clase concreta.
Esto implica que para hacer tu patrón Observer con la implementación de Java tienes una limitación: Tu objeto debe heredar de Observable, y si ya extiende otro objeto, no puedes hacer nada. ¿Que pasa si quieres customizar tu objeto Observable? Sigues teniendo que extender la clase. Y si quieres componer un objeto con otro que extienda Observable, olvídate de usar sus métodos para cambiar y leer el estado porque son protected.
Por supuesto esto tiene una explicación y es que estas dos clases, tal y como podéis ver en su documentación, existen desde el JDK 1.0. Por este y otros motivos se recomienda implementar tu propio patrón Observer a través de interfaces.
Puedes encontrar un ejemplo sencillo y comentado de la implementación del patrón observer en mi repositorio de Github.