El uso de esta técnica de desarrollo, nos ha permitido afrontar simulaciones de alto nivel de complejidad con resultados satisfactorios para los clientes y en tiempos muy cortos, lo que ha redundado en excelentes resultados para la empresa.
Programación multihilo
- Un programa multihilo contiene dos o más partes que se pueden ejecutar de manera concurrente o simultánea.
- Cada parte del programa se denomina hilo (thread), y cada hilo define un camino de ejecución independiente.
- Es una forma especializada de multitarea.
El modelo de Hilo en Java
El intérprete de Java y todas las bibliotecas de clases se han diseñado con base al modelo multihilo para permitir que todo el entorno sea asíncrono. Esto aumenta la eficacia, impidiendo el desaprovechamiento de ciclos de la CPU; esto proporciona una ventaja significativa a la hora de pedir recursos al sistema operativo ya que en el esquema de un solo hilo, cuando un programa suspende su ejecución en la espera de un recurso, el programa entero se detiene. En la programación multihilo, esto no ocurre. Por ejemplo, el tiempo de inactividad que se produce cuando un hilo lee datos de la red o espera a que el usuario introduzca una información, puede ser aprovechado por otro.
Estados de los Hilos en Java
Un hilo puede tener los siguientes estados:
- Ejecución: El hilo está siendo ejecutado.
- Listo para ejecución: El hilo está en la lista de hilos listos para ser ejecutados, tan pronto disponga cada uno de tiempo de la CPU.
- Suspensión: La ejecución del hilo es suspendida temporalmente.
- Reanudación: Un hilo suspendido vuelve a ejecutarse continuando su tarea en el punto donde la dejó.
- Bloqueado: Un hilo está en espera de un determinado recurso.
En cualquier instante un hilo puede detenerse, finalizando su ejecución de forma inmediata. Y una vez detenido, no podrá reanudarse.
Propiedades de los Hilos en Java
Prioridades: Java asigna una prioridad que determina cómo se debe tratar un hilo con relación a los demás. La prioridad de los hilos se define en un rango de números enteros (1 – 10) que especifican la prioridad relativa de un hilo sobre otro. La prioridad de un hilo se utiliza para decidir cuando se debe pasar de la ejecución de un hilo a la del siguiente. A esto se denomina cambio de contexto. Las reglas para el cambio de contexto son las siguientes:
Un hilo puede ceder voluntariamente su acceso al CPU. Esto pasa cuando un hilo entra en las siguientes situaciones:
- Termina su ejecución o efectúa un abandono explícito (yield),
- Se queda dormido (sleep), o bloqueado por una E/S pendiente. Cuando esto ocurre, se examinan todos los demás hilos, y se le asigna la CPU al que esté preparado para ejecutarse y tenga la más alta prioridad.
Un hilo puede ser desalojado por otro con prioridad más alta. En este caso un hilo con prioridad más baja que no libera el procesador es simplemente desalojado, sin tener en cuenta lo que está haciendo, por otro de prioridad más alta. Básicamente, cuando hilo de prioridad más alta desee ejecutarse, lo hará. A esto se le denomina tarea de desalojo.
Programación Multihilos en Java
La clase Thread y la interfaz Runnable
Java maneja dos formas de programar hilos, utilizando la clase Thread o la interfaz Runnable.
La clase Thread tiene varios métodos que ayudan a la gestión de los hilos. A continuación se muestran algunos de ellos:
- void start(): Empieza la ejecución del Thread (hilo). Invoca al método run() de dicho hilo.
- public void run(): Constituye el cuerpo de un hilo en ejecución. Este es el único método del interfaz Runnable. Es llamado por el método start() después de que el hilo apropiado del sistema se haya inicializado.
- void stop():
- static void sleep (long millis) : permite que el thread espere determinado tiempo que se especifica en el parámetro (en milisegundos). Da oportunidad a los threads de cualquier prioridad de ejecutarse.
- static void yield (): permite a los threads que se encuentran en estado listo (runnable) y que tienen la misma prioridad del thread que ejecuta el yield, ejecutarse.
Da oportunidad solamente a threads que tengan igual prioridad de ejecutarse.
- void suspend():
- public final void resume() : Reanuda la ejecución de un Thread que estaba previamente en estado suspendido.
- public final boolean isAlive():
- public final void setPriority(int newPriority): Asigna al hilo la prioridad indicada por el valor pasado como parámetro. Hay bastantes constantes predefinidas para la prioridad, definidas en la clase Thread, tales como MIN_PRIORITY, NORM_PRIORITY y MAX_PRIORITY, que toman los valores 1, 5 y 10, respectivamente.
- public final int getPriority(): Este método devuelve la prioridad del hilo de ejecución en curso.
- public final void setName( String ): Este método permite identificar al hilo con un nombre. De esta manera se facilita la depuración de programas multihilo.
- public final getName(): Este método devuelve el valor actual, del nombre asignado al hilo en ejecución.
Ejemplo de Hilos creados con la clase Thread
El siguiente programa hace dos numeraciones del 0 al 10 utilizando dos hilos diferentes, para saber que hilo imprime el número en pantalla se utiliza el método getName().
class HiloSencillo extend Thread {
public HiloSencillo (String str)
{
super(str);
}
public void run ()
{
for (int i=0; i<10; i++) {
System.out.println(i + " " + getName());
try {
Thread.sleep(int)(Math.random() * 1000));
} catch(Exception e) {}
}
}
}
class EjemploDosHilos {
public static viid main (String[] args) {
new HiloSencillo ("Hola").start();
new HiloSencillo ("Adios").start();
} }
El resultado tendrá un aspecto aproximado al siguiente:
Otra forma de crear un hilo es creando una clase que implemente la interfaz Runnable. La interfaz Runnable define el método Run que debe ser implementado en la clase que se desea ejecutar en un hilo independiente, para ejecutar la clase, esta se debe pasar como argumento en el constructor de la clase Thread.
A continuación se muestra el programa de hilos anterior pero ahora utilizando la interfaz runnable:
class HiloSencillo2 implements Runnable {
private String nombre;
public HiloSencillo2 (String str) {
this.nombre=str;
}
public String getName () {
return this.nombre;
}
public void run () {
for (int i=0; i<10; i++) {
System.out.println (i + " " + getName());
try {
Thread.sleep((int)(Math.random() * 1000));
}
}
}
class EjemploDosHilos {
public static void main (String[] args) {
new Thread(new HiloSencillo2("Hola")).start();
new Thread(new HiloSencillo2("Adios")).start();
}
}
Su aplicación en los negocios
Recientemente, nos pidieron que desarrollaramos 2 simulaciones, una para el control y operación del paso de automotores del Segundo Piso del Periférico Sur y otra para presentar el aforo en casetas desde 2 puntos de vista, la primera cuando se tiene determinado el número de carriles de una caseta y se ingresa el aforo de todo tipo de automotores y la segunda es: dando un aforo que deberá cruzar por los diversos carriles de pago en un espacio, determinar el tamaño de la caseta.
El tiempo de desarrollo fue corto pero lo más importante, el Cliente quedo satisfecho, hoy en día estamos aplicando este concepto de desarrollo en varios de nuestros compromisos que más adelante comentaremos por esta página web.
comments powered by Disqus