En este volumen os vamos a recomendar ciertas estructuras para programar de forma concurrente con un mejor rendimiento dependiendo de en qué casos nos encontremos.
Una estructura de datos muy útil es la cola concurrente.
La clase ConcurrentLinkedQueue nos proporcionará una cola FIFO (Primero en entrar, primero en salir) escalable, concurrente y no bloqueante, de esta forma no tendremos que gestionar «manualmente» la cola para que no tengamos «problemas».
Tenéis toda la información sobre ConcurrentLinkedQueue en el JavaDoc, ahí podéis mirar todos los métodos y para qué sirven cada uno. Los métodos son parecidos a la LinkedQueue de toda la vida.
Con esta estructura de datos podemos solucionar de una forma elegante el conocido problema del productor/consumidor porque basta con poner la siguiente estructura para la gestión de la cola de mensajes:
[java]Queue
También podemos usar la interfaz BlockingQueue que contiene varios tipos de colas bloqueantes. Estas colas permiten poner un número determinado máximo de elementos así como un timeout para las esperas en cola llena y cola vacía, es decir, una mayor flexibilidad para gestionar la cola correctamente.
Algunas clases que implementa esta interfaz son: ArrayBlockingQueue basado en la conocida estructura de Arrays, DelayQueue que permite extraer un objeto después de cierto tiempo definido, LinkedBlockingDeque, LinkedBlockingQueue basado en nodos enlazados, LinkedTransferQueue, PriorityBlockingQueue, SynchronousQueue que permite que cada elemento introducido, espere a ser extraído antes de meter el siguiente.
Java permite también métodos sincronizados a través de colecciones para garantizar la exclusión mutua. Por ejemplo tenemos lo siguiente:
[java] List listaConcurrente = Collections.synchronizedList(new ArrayList()); [/java]
Si la colección es muy grande, será poco eficiente, y será mejor utilizar colecciones concurrentes que han sido creadas específicamente para tal fin como por ejemplo ConcurrentHashMap que implementa un HashMap concurrente en la que las operaciones get o put se pueden dar simultáneamente. También tenemos CopyOnWriteArrayList que es la versión concurrente del conocido ArrayList.
En Java también tenemos herramientas para que los distintos hilos se puedan coordinar satisfactoriamente. Tenemos la clase CyclicBarrier que permite que los hilos se esperen los unos a los otros hasta cumplir una condición, por ejemplo tener 100 usuarios viendo la TV, si hay 99 se esperan antes de «encenderla». Otras clases de este estilo es CountDownLatch.
Estas últimas herramientas son más avanzadas y no las vamos a utilizar en nuestro particular curso de Java.