Se habla de concurrencia cuando se ejecutan varios procesos simultáneos.
La concurrencia aparece cuando dos o más procesos son simultáneos. Un caso particular es el paralelismo (programación paralela).
- Los procesos pueden “competir” o colaborar entre sí por los recursos del sistema. Por tanto, existen tareas de colaboración y sincronización.
- Java posibilita la programación concurrente a través de threads.
- Los threads son procesos ligeros, con línea de flujo de control propia pero que comparte el espacio de direcciones del programa.
- Los threads hacen posible la ejecución concurrente de código. Los cambios de contexto son menos costosos en tiempo de ejecución.
BENEFICIO DE HACER UN PROGRAMA CONCURRENTE
- Velocidad de ejecución. Al subdividir un programa en procesos, éstos se pueden “repartir” entre procesadores o gestionar en un único procesador según importancia.
Java proporciona un API para el uso de hilos: clase Thread dentro
del paquete java.lang.Thread. Cuando arranca un programa existe un hilo principal (main), y luego
se pueden generar nuevos hilos que ejecutan código en objetos
diferentes o el mismo.
La clase Thread dispone de una serie de métodos para caracterizar
el thread/hilo en el programa, es importante sobreescribir el método run(), para que el hilo realice su función e invocar al método start() para darle vida al hilo.
![]() |
Esquema de los diferentes estados en los que puede encontrarse un hilo. |
- Nuevo: Se ha creado un objeto hilo, pero todavía no se le ha asignado ninguna tarea. Para ello, se ha de llamar a su método start() y el hilo pasará al estado preparado.
- Preparado: El hilo está preparado para ejecutarse, pero el planificador de hilos es quién debe decidir si puede hacerlo o debe esperar.
- En ejecución: Una vez el hilo puede acceder a tiempo de CPU, se ejecutará. Si el hilo finaliza su trabajo completamente, pasará al estado muerto. Si el planificador de hilos decide que ha cumplido su periodo de tiempo y el hilo no ha finalizado su trabajo, pasará al estado preparado y esperará a que el planificador de hilos vuelva a darle permiso para ejecutarse.
- Bloqueado: El hilo no puede ejecutarse porque espera que ocurra algo. En cuanto ocurra lo que le está dejando bloqueado, pasará al estado preparado.
- Muerto: El hilo ha finalizado su tarea y deja de existir.
EJEMPLO PRÁCTICO
Realizar un programa concurrente en java, mediante la utilización de hilos y sockects. Este programa indica al cliente que ingrese un mensaje, este va al servidor y el servidor le devuelve el mismo mensaje.
CLASE CLIENTE
CLASE MANEJOTHREAD
CLASE SERVIDOR
SALIDA DEL PROGRAMA
BIBLIOGRAFÍA:
http://www.ingenieroinformatico.org/2012/01/concurrencia-en-java/
http://www.ctr.unican.es/asignaturas/procodis_3_II/Doc/Procodis_3_01.pdf
http://www2.ulpgc.es/hege/almacen/download/20/20233/tema1.pdf
CLASE CLIENTE
- Se importa las librerías de las clases necesarias para el programa
- La clase ClienteEco permite el envió de un mensaje a un servidor y la vez recibe el mismo mensaje atra vez de este. Para la ejecución del programa se colocara el método main el cual recibe argumento de entrada del tipo String.
- En esta clase se crea un objeto del tipo Socket, llamado cliente, este se lo instancia con el constructor de la clase, el cual recibe como argumento de entrada dos parámetros, uno la dirección IP y segundo el puerto por el cual el cliente será escuchado.
- Creamos un objeto del tipo BufferedReader llamado lecturaCliente, instanciado con el constructor de la clase, recibiendo como argumento de entrada lo que va a leer.
- Se crea un objeto del tipo PrintWriter, llamado escribir, se lo instancia con el constructor de la clase enviándolo como argumento de entrada lo que se enviará al cliente.
- Creamos otro BufferedReader llamado entrada, instanciandolo con el constructor de la clase y enviando como argumento de entrada, que leerá desde el teclado.
- A continuación se imprimirá por pantalla el mensaje, Ingrese el mensaje, donde el usuario ingresará el mismo.

- Se realiza un condicional, en donde mientras el cliente ingrese algún mensaje, se realizará lo siguiente.
- Se enviará el mensaje al servidor mediante el objeto creado escribir.
- Por pantalla se imprimirá el mensaje enviado por el servidor al cliente.
- Finalmente se utiliza el método close(), para cerrar el socket utilizado.
- Es importante el manejo de excepciones con try-catch.
CLASE MANEJOTHREAD
- Se importa las librerías de las clases necesarias para el programa
- La clase ManejoThread hereda de la clase Thread, está permite la utilización de hilos para generar un programa concurrente.
- Presenta 3 tipos de atributos uno del tipo Socket, otro de tipo int y el último de tipo String.
- Se realiza el constructor de inicializacion de la clase, mandando como argumento de entrada un objeto del tipo socket.
- Como los atributos utilizados son private es necesario la creación de los getters y setters de cada uno.
- Como esta clase se extiende de Thread, se debe sobreescrirbir el método run(), este tendrá la funcionalidad de los hilos a ejecutarlra
- Para esto se crea un objeto del tipo BufferedReader llamado lectura, instanciado con el constructor de la clase, recibiendo como argumento de entrada lo que va a leer.
- Se crea un objeto del tipo PrintWriter, llamado escribir, se lo instancia con el constructor de la clase enviándolo como argumento de entrada lo que se enviará al cliente.
- Es necesario un boolean para controlar la ejecución de los hilos.
- Se crea un lazo condicional mientras sea verdadera se realizará lo siguiente, el atributo sms se instancia con el objeto lectura, este permite leer el mensaje que envió el cliente.
- Por pantalla se imprimirá el mensaje que se recibió del cliente.
- Se usa un condicional para comprobar si el mensaje es nulo solo se lo imprime, caso contrario el mensaje se envía al cliente.
- Finalmente se cierra el socket creado.
- Es importante el manejo de excepciones, para lo cual se utilizó el try y catch
- Importamos las librerías de las clases necesarias
- La clase Servidor recibirá el mensaje del cliente y lo imprimirá por pantalla, a la vez que este mensaje es devuelto al cliente
- Se utiliza el método main para la ejecución del programa, este recibe un argumento de entrada el cual es el número de puerto por donde escuchará las peticiones.
- Se utiliza un condicional, el cual comprueba que el número de argumentos de entrada sea correcto caso contrario manda un mensaje de información.

- Se crea un atributo de tipo int, instanciado con el número de puerto ingresado ha este se lo realiza un casting.
- Se crea un objeto del tipo ServerSocket, llamado serverSocket, este se lo instancia con el constructor de la clase, se lo mando como argumento de entrada el numero de puerto
- Si todo se ejecutó de manera correcta, por pantalla se imprimirá Escuchando, el cual indica que el servidor esta esperando peticiones de clientes.

- Se realiza un lazo infinito, en donde se creará un objeto del tipo Socket, aquí se establece la conexión entre cliente y servidor mediante el socket creado. Por pantalla se imprimirá que la conexión fue aceptada.
- Se crea un objeto del tipo ManejadorThread, este recibe como argumento de entrada un objeto del tipo Socket en este caso será el cliente.
-
Se crea un objeto del tipo Thread, que será el hilo que se crea para atender a cada cliente, este recibe como argumento de entrada un objeto del tipo ManejadorThread. Finalmente utilizamos el método start(), para darle vida al Thread.

- Hay que recordar que es importante utilizar el manejo de las excepciones, utilizando el try y catch.
SALIDA DEL PROGRAMA
- EJECUCIÓN DEL SERVIDOR
- EJECUCIÓN DE CLIENTES
- EJECUCIÓN DE PETICIONES DE 3 CLIENTES
BIBLIOGRAFÍA:
http://www.ingenieroinformatico.org/2012/01/concurrencia-en-java/
http://www.ctr.unican.es/asignaturas/procodis_3_II/Doc/Procodis_3_01.pdf
http://www2.ulpgc.es/hege/almacen/download/20/20233/tema1.pdf