Multiprocesos en Java: Como usar Hilos(Threads)

20
13195

En Java, así como en cualquier lenguaje de programación, la principal estructura de ejecución de instrucciones es la estructura secuencial, en la que cada comando, cada línea, cada instrucción se ejecuta una después de otra. El código se ejecuta de arriba hacia abajo y cada línea es ejecutada según el orden en que halla sido escrita por el programador.

Veamos el diagrama de flujo:

Flujo

Dentro de la ejecución del programa puede que intervengan otras estructuras como las repetitivas o las selectivas, pero eso es harina de otro costal. Estos temas los veremos más adelante en futuras aportaciones.

En ocasiones puede que el usuario necesite llevar a cabo 2 o más procesos a la vez. Supongamos que queremos realizar 3 procesos al mismo tiempo, como lo vemos en este modelo:

Flujo

Esto es completamente IMPOSIBLE ya que el procesador de una computadora no es capaz de realizar estas funciones. Sin embargo existen alternativas, como los Hilos o Threads.

Si vemos el diagrama de arriba, podemos identificar 3 hilos: Proceso 1, Proceso 2 y Proceso 3. Pero, ya hemos dicho que esto no es posible de la forma como lo hemos presentado en el diagrama de flujo.

Si intentamos utilizar una estructura secuencial para ejecutar 3 procesos, obtendremos el siguiente resultado:

Flujo

Existe una serie de inconvenientes con esto: el proceso 1 sólo se ejecutará cuando halla terminado el proceso 2. El proceso 3 se empezará a ejecutar cuando halla terminado el proceso 1 y 2.

Con los hilos o threads, podemos obtener una ejecución lo más cercana posible al modelo de los 3 hilos que presenté arriba. Los threads son estructuras secuenciales que combinan las líneas de 2 o más procesos en un solo proceso.

Si lo expresamos con un diagrama de flujo se vería de la siguiente forma:

Flujo

Los comandos en azul pertenecen al proceso 1, los comandos en rojo son del proceso 2 y el rojo del proceso 3.

La forma como se ejecutan los procesos es completamente aleatoria. Puede que se inicie la ejecución con el proceso 2, luego el 2, luego el 3, luego el 1 y así sucesivamente.

No siguen un orden específico. Esto permite que los 3 vallan corriendo al mismo tiempo, dando como resultado algo bastante parecido a aquel modelo que ya hemos dicho que no es posible obtener con los procesadores de nuestras computadoras.

Veamos como funcionan los Threads con una aplicación en Java. Vamos a Netbeans y creamos un proyecto llamado Threads. Insertamos un JFrame y le colocamos un botón con el que iniciaremos la ejecución se los Threads.

java threads

Ahora vamos al código y declaramos 3 variables tipo Thread.

 

java threads

Ahora vamos a programar el botón que colocamos en el JFRame.

Dentro del código del botón iniciaremos los threads. Colocamos lo siguiente:

 

java threads

Como podemos observar, Netbeans marca 3 errores con la inicialización de los threads. Esto se debe a que necesitamos implementar la interfaz Runnable en la Clase de nuestra JFrame.

Image

Aún así Netbeans marca un error. Le damos clic en el ícono de la izquierda para corregir el error. Nos aparecerá la opción “Implement all abstract methods”.

java threads

Al hacer clic desaparecerá el error. Al final del código se agregará lo siguiente:

java threads

En este nuevo método que se ha agregado es donde se coloca el código que ejecutarán los threads.

Para ver como se ejecutan los threads, veremos una carrera de 3 procesos. Primero declararemos 3 variables, c1, c2 y c3. Serán del tipo entero y las inicializaremos en 0.

Luego introduciremos los siguientes métodos:

 

Estos métodos lo que harán es que le agregarán una unidad a cada una de las variables, es decir, c1, c2 y c3.

Sin título

Ahora nos dirigimos al final del programa, donde está el método public void run().

Allí colocamos lo siguiente:

 

Sin título

Esto funciona de la siguiente manera:

La variable ct adoptará el valor del CurrenThread, es decir, el hilo que se esté ejecutando en determinado instante.

Mientras ese hilo que se esté ejecutando sea el hilo1, se ejecutará la función corredor1 que es la encargada de aumentar la variable c1. La función  System.out.println(“Corredor 1: ” + c1); imprime el valor de c1 en la parte inferior de Netbeans IDE.

Se repite el mismo proceso para los otros 2 hilos. Lo que queremos darnos cuenta es como Java ejecuta el código. Lo hemos colocado uno debajo del otro, como una secuencia, pero al ejecutar el programa y presionar el botón nos damos cuenta de que no es una secuencia.

Cuando ejecutamos el programa obtenemos lo siguiente:

Corredor 1: 1
Corredor 1: 2
Corredor 3: 1
Corredor 2: 1
Corredor 3: 2
Corredor 1: 3
Corredor 3: 3
Corredor 2: 2
Corredor 3: 4
Corredor 1: 4
Corredor 3: 5
Corredor 2: 3
Corredor 3: 6
Corredor 1: 5

Sin título

Como podemos observar, el proceso inició ejecutándose con el método 1 (corredor1) pero de la tercera línea en adelante se volvió aleatorio, es decir, el proceso 2 y 3 empezaron a ejecutarse a medida que el proceso 1 también se ejecutaba.

Si detenemos el programa y empezamos una nueva ejecución obtendremos otro tipo de comportamiento:

Sin título

Ahora el primer proceso en ejecutarse fue el proceso 2. Es probable que cada vez que ejecutemos el programa obtendremos resultados diferentes. Todo depende de nuestras computadoras y la manera como ellas decidan ejecutar las tareas. Lo importante es que no es necesario esperar que el proceso 1 se termine de ejecutar para empezar con el 2 y el 3, sino que los 3 se ejecutarán en manera conjunta.

Existen otros tipos de métodos para trabajar con threads, sin embargo para mi es más fácil implementar la interfaz runnable. Es cuestión de gustos y las estructuras varían de programador a programador.

Aquí está el archivo zip con el proyecto de Netbeans:

http://docs.google.com/file/d/0B0hsUkhqWH97UFhaeXloc1JkTlU/edit?usp=sharing

Espero que les halla gustado este aporte. Espero sus comentarios.

Saludos.

  • Diego

    Lo que desea hacer es pedirle al usuario la cantidad de hilos que se desean ejecutar con el objetivo de que un algoritmo se ejecute en menos tiempo, el algoritmo procesa dos archivos de gran peso y leen secuencias de ADN, si lanzo todo por un hilo es muy demorado, por lo que necesitaría de varios hilos para hacer el proceso mas óptimo.

    • Los threads en Java no te permiten hacer un proceso más rápido, sino hacer dos procesos a la vez. La capacidad de procesamiento de una computadora reside exclusivamente en el procesador del equipo (cantidad de núcleos, frecuencia, etc). Los threads se utilizan por ejemplo cuando hay programas con interfaces gráficas donde un hilo realiza un proceso mientras el otro se encarga de actualizar los gráficos de la interfaz. No existe tal cosa como dividir un proceso en varias subrutinas y ejecutarlos más rápidamente. Me mencionas que deseas procesar dos archivos, pues podrías asignrale un hilo a cada archivo, sin embargo el tiempo de proceso será dividido entre los dos, por lo que no te será posible obtener más velocidad de procesamiento sino un resultado final mas o menos equitativo en cuanto al tiempo total que toma el proceso en ejecutarse

  • diego

    Gracias por tu respuesta se realizaria con el objetivo de ejecutar un proceso mucho mas rapido

  • diego

    Con el objetivo de realizar un proceso mucho mas rapido

  • diego

    Hola amigo gracias por el aporte una pregunta es posible pedirle al usuario la cantidad de hilos que se desean ejecutar para realizar el proceso ejemplo: usuario ingrese cantidad de hilos 5 y se ejecuten 5 hilos
    te agradezco tu respuesta y si tienes un ejemplo

  • Kanfor

    Gracias. Es el único tutorial claro de todo internet.

  • Bryan

    Amigo por favor podrías Recuperar de nuevo las Imágenes las 10 primeras imagenes no se muestran estan con error te agradeceria mucho que lo aregles gracias y buenos temas en general bun post

  • se le agradece por toda la info… y por explicarlo de una forma tan práctica y sencilla

  • Edwin

    amigo, puedes darme el ejemplo para probarlo?

  • Hola gracias por sus comentarios. Creo que se refiere a esto: http://panamahitek.files.wordpress.com/2013/02/sin-tc3adtulo2.png

  • Gustavo

    Hola es muy claro y didactico, la unica duda que tengo es donde inicializas los Threads.start() para que cambien al estadopreparado.

  • muy bien explicado amigo te felicito estare en contacto contigo aqui guardare tu pagina espero podamos conversar he intercambiar ideas gracas

    • Muchas gracias por sus comentarios. Estoy siempre a disposición de cualquiera que necesite ayuda.