Bienvenidos sean a este post, Java es un lenguaje de programacion multithreading (es decir multiprocesos) lo cual nos permitira crear programas que podran corrar multiples procesos al mismo tiempo, un programa de este estilo puede contener dos o mas partes que corren simultaneamente y cada parte corre tareas distintas permitiendo un uso optimo de tu equipo si posee mas de una CPU.
Por definicion, la multitareas (multitasking) se da cuando multiples procesos comparten recursos de procesamiento en comun como el caso de una CPU, multi-threading expande la idea de multitasking dentro de una aplicacion porque nos permite subdividir operaciones especificas dentro de una aplicacion simple en diversos procesos, cada uno de estos procesos pueden correr en paralelo, el S.O divide los tiempos de procesamiento no solamente entre aplicaciones sino entre los procesos de las aplicaciones, este tipo de procesamiento te permite escribir en una forma donde multiples actividades pueden proceder simultaneamente de una misma aplicacion, pasemos a nuestra siguiente explicacion que son los ciclos de vida de un proceso.
En el ciclo de vida de un proceso va a traves de varias instancias, por ejemplo un proceso nace, inicia, corre y muere, a continuacion enlistaremos las instancias de un ciclo de vida:
- New, un nuevo proceso comienza su ciclo de vida con el estado new, permanece en este estado hasta que el proceso inicia, tambien se lo puede conocer como estado de nacimiento.
- Runnable, cuando es iniciado el proceso se convierte en este estado, un proceso en este estado se considera que esta ejecutando su tarea
- Waiting, en algunas ocasiones un proceso pasa al estado waiting mientras el proceso espera por otro para ejecutar otra tarea, este vuelve a su estado anterior solamente si otro proceso notifica al estado actual para continuar su ejecucion
- Timed Waiting, un proceso en estado Runnable puede pasar a Waiting por una determinada cantidad de tiempo y una vez pasado este tiempo vuelve al estado Runnable
- Terminated (Muerto), se entra en este estado cuando un proceso completa su tarea o es terminado
Cada proceso tiene su prioridad que ayuda al S.O. a determinar el orden en que los procesos seran organizados, las prioridades tienen el siguiente orden:
- MIN_PRIORITY, tiene una constante de 1
- NORM_PRIORITY, tiene una constante de 5 (el mas habitual)
- MAX_PRIORITY, tiene una constante de 10
Procesos con una prioridad mas alta son mas importantes para un programa y deberian ubicar un tiempo de procesador antes que los procesos de baja prioridad, sin embargo esto no garantiza el orden en el cual los procesos se ejecutaran ya que son dependientes de la plataforma, a continuacion hablaremos sobre algunos de los metodos disponibles:
- public void start(), inicia el proceso en un camino separado de ejecucion, luego invoca a run() en el objeto de tipo Thread
- public void run(), si este objeto fue instanciado usando destino Runnable separado, el metodo es invocado en ese objeto Runnable
- public final void setName(String nombre), cambia el nombre del objeto Thread y tambien existe un metodo getName() para recuperar dicho nombre
- public final void setPriority(int prioridad), setea la prioridad del objeto Thread y el valor puede ser entre 1 y 10
- public final void setDaemon(boolean var), un parametro de tipo verdadero (true) denota que el objeto sera un proceso de tipo daemon, en windows puede considerarse servicio
- public final void join(long miliseg), el actual proceso invoca este metodo en un segundo proceso el cual bloquea el actual proceso hasta que termina o pasaron los milisegundos informados
- public void interrupt(), interrumpe el proceso, provocando que cualquier otro proceso bloqueado por este pueda continuar
- public final boolean isAlive(), devuelve verdadero (true) si el proceso sigue vivo, lo cual es en cualquier entre el inicio del proceso y la finalizacion del mismo
Los metodos visto anteriormente son invocados para un objeto de tipo Thread en particular, los siguientes metodos que veremos son de tipo static y cualquiera de estos metodos realiza la accion en el proceso que esta corriendo actualmente:
- public static void yield(), hace que el subproceso actualmente en ejecución ceda a otros subprocesos de la misma prioridad que están esperando para ser programados.
- public static void sleep(long miliseg), hace que el proceso actual se bloquee por al menos la cantidad de milisegundos informada
- public static boolean holdsLock(Object x), devuelve verdadero si proceso actual mantiene el bloqueo sobre el objeto informado
- public static Thread currentThread(), devuelve una referencia al proceso que esta corriendo actualmente, el cual es el proceso que invoca este metodo
- public static void dumpStack(), imprime un vuelco de la pila (stack) para el proceso que esta actualmente corriendo, su mayor utilidad es para hacer una depuracion de aplicaciones multithreading
Primero veamos el caso de implementar un thread por medio de una interfaz Runnable, para ello deberemos seguir tres pasos basicos:
- Se debe implementar run desde una interfaz Runnable, esto creara un punto de entrada para nuestro proceso (thread) y podras volcar toda la logica de negocios dentro de este metodo.
- Se debe instanciar un Thread por medio de un constructor, veremos uno en el ejemplo
- Una vez creado este objeto, se puede iniciar con el metodo start la cual llama al metodo run
Veamos un ejemplo para poder implementarlo y entenderlo:
DemoThread.java
class RunnableDemo implements Runnable
{
private Thread t;
private String threadNombre;
RunnableDemo(String nombre)
{
threadNombre = nombre;
System.out.println("Creando " + threadNombre);
}
public void run()
{
System.out.println("Corriendo " + threadNombre);
try
{
for(int i = 4; i > 0; i--)
{
System.out.println("Thread: " + threadNombre
+ ", " + i);
Thread.sleep(50);
}
}
catch (InterruptedException e)
{
System.out.println("Thread: " + threadNombre
+ " interrumpido.");
}
System.out.println("Thread: " + threadNombre + " saliendo.");
}
public void start()
{
System.out.println("Iniciando " + threadNombre);
if (t == null)
{
t = new Thread(this, threadNombre);
t.start();
}
}
}
public class DemoThread
{
public static void main(String[] args)
{
RunnableDemo R1 = new RunnableDemo( "Thread-1" );
R1.start();
RunnableDemo R2 = new RunnableDemo( "Thread-2" );
R2.start();
}
}
En este caso primero crearemos una clase llamada RunnableDemo la cual implementara a la interfaz Runnable, en la cual tendremos dos variables, luego nuestro constructor para esta clase donde lo utilizaremos para asignar un nombre al Thread, despues definiremos al metodo run() donde mostraremos el nombre del Thread y a su vez usaremos un metodo for para contar cuatro numeros y que acompañen al nombre del Thread para en este caso pausarlo uno 50 milisegundos, tambien usaremos un metodo try/catch para capturar cualquier error y mostrarlo en pantalla, despues mostraremos un mensaje de salida, por ultimo definiremos al metodo start() donde chequearemos si t es igual a null y en caso de ser verdadero creara un nuevo Thread, donde primero informaremos el objeto, en este caso usamos this para decir que es este y luego le pasamos el nombre que asignamos a nuestro proceso Thread, para finalmente iniciarlo por medio de start(), en el cuerpo de nuestra clase solamente crearemos dos objetos de la clase anteriormente definida, RunnableDemo, donde le informaremos el nombre y lo iniciaremos, si lo compilamos y ejecutamos obtendremos la siguiente salida:
tinchicus@dbn001vrt:~/programacion/java/codigo$ java DemoThread
Creando Thread-1
Iniciando Thread-1
Creando Thread-2
Iniciando Thread-2
Corriendo Thread-1
Thread: Thread-1, 4
Corriendo Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread: Thread-1 saliendo.
Thread: Thread-2 saliendo.
tinchicus@dbn001vrt:~/programacion/java/codigo$
Como pueden ver al principio creamos un Thread y luego lo iniciamos, para luego crear otro Thread e iniciarlo, observen como van alternando entre uno y otro para mostrarnos el valor del bucle for en el metodo run() para finalmente mostrarnos la salida, nuestro siguiente tema sera como crear un Thread extendiendo la clase Thread, para realizar esto se deben hacer dos pasos:
- Necesitas sobreescribir el metodo run() disponible en la clase Thread y al igual que antes nos permite utilizarlo para nuestro programa.
- Y como en el caso anterior tambien debemos implementar start() para poder usarlo con nuestro objeto creado
En este caso vemos que se nos facilita la posibilidad de implementar los Threads, para entender el concepto veamoslo a traves del siguiente ejemplo:
DemoThread2.java
class ThreadPrueba extends Thread
{
private Thread t;
private String threadNombre;
ThreadPrueba( String nombre )
{
threadNombre = nombre;
System.out.println("Creando " + threadNombre);
}
public void run()
{
System.out.println("Corriendo " + threadNombre);
try
{
for(int i = 4; i > 0; i-- )
{
System.out.println("Thread: " + threadNombre
+ ", " + i);
Thread.sleep(50);
}
}
catch (InterruptedException e)
{
System.out.println("Thread " + threadNombre
+ " interrumpido.");
}
System.out.println("Thread " + threadNombre + " saliendo.");
}
public void start()
{
System.out.println("Iniciando " + threadNombre);
if (t == null)
{
t = new Thread(this, threadNombre);
t.start();
}
}
}
public class DemoThread2
{
public static void main(String[] args)
{
ThreadPrueba T1 = new ThreadPrueba( "Thread-1" );
T1.start();
ThreadPrueba T2 = new ThreadPrueba( "Thread-2" );
T2.start();
}
}
En este caso trabaja de forma similar al caso anterior pero nuestra mayor diferencia sera que en lugar de implementar una interfaz y tener que definir si o si nuestros metodos run y start extenderemos a la clase Thread y por esto no definiremos sino que sobreescribiremos los metodos run y start que estan disponibles en la clase pero no es obligatorio sino lo hacemos para poder utilizar una funcion mejor definida por nosotros pero en ambos casos todos los metodos y funciones trabajan de la misma forma, si lo compilamos y ejecutamos veremos esta salida:
tinchicus@dbn001vrt:~/programacion/java/codigo$ java DemoThread2
Creando Thread-1
Iniciando Thread-1
Creando Thread-2
Iniciando Thread-2
Corriendo Thread-1
Thread: Thread-1, 4
Corriendo Thread-2
Thread: Thread-2, 4
Thread: Thread-1, 3
Thread: Thread-2, 3
Thread: Thread-1, 2
Thread: Thread-2, 2
Thread: Thread-1, 1
Thread: Thread-2, 1
Thread Thread-1 saliendo.
Thread Thread-2 saliendo.
tinchicus@dbn001vrt:~/programacion/java/codigo$
Como pueden ver es exactamente la misma salida y esto significa que podemos utilizar cualquiera de las dos formas y obtendremos la misma utilidad.
En resumen, hoy hemos visto una introduccion a multithreading, hemos visto los posibles estados que pueden tener, algunos metodos disponibles en el objeto creado y algunos metodos vistos de tipos static, como implementar los Multi Threads para poder tener dos procesos corriendo al mismo tiempo, hemos visto a traves de la implementacion por medio de la interfaz Runnable, otro caso extendiendo la clase Thread. Espero les haya sido de utilidad, les dejo algunas de mis redes sociales para seguirme o recibir una notificacion cada vez que subo un nuevo post:


Donación
Es para mantenimento del sitio, gracias!
$1.50





