MULTIHILO en Java
LOS THREADS O PROGRAMACIÓN MULTIHILO en Java A. Introducción Mientras la ejecucion de los proyectos tienen lugar muchas operaciones que precisan de una espera; en busca de una interaccion con el exterior, dejando pasar el tiempo, esperando a que otro proceso acabe... Java faculta que estos tiempos desaprovechados sean utilizados por el programador para hacer algunas tareas, y asi aprovechar el microprocesador mientras toda la ejecucion del programa. Para ello implementa el concepto de threads, o hilos de control del programa. Mediante el uso de varios threads, se alcanza ejecutar varios procesos en paralelo, de manera que cuando uno de ellos este esperando determinado evento, permita que el microprocesador ejecute determinadoo de los otros threads en espera. Cuando el evento que el primer thread esperaba sucede, de nuevo se intercambian los threads para que el primer thread continue su ejecucion. Todo esto viene a suplir a la técnica de exclusión mutua denominada utilización de semáforos, extendida entre los programadores de C en UNIX. B. Utilización de thread Para crear un thread, se ha de implementar una clase, extendiendo la clase fundamento Runnable, y crear un objeto de la clase Thread. Este objeto representara un nuevo hilo de control, que sera accionado cuando invoquemos al metodo start() del thread. En ese momento este hilo se activara, ejecutando (si el planificador de hilos estima que es el momento), el metodo run() de la clase en que todo esto suceda. Por ejemplo, el proximo proyecto emplea dos hilos, el hilo común main, y el hilo thDemo que creamos: import java.io.*; import java.net.*; class ThreadDemo implements Runnable { ThreadDemo() { Thread thDemo = new Thread( this, "ThDemo" ); thDemo.start(); } public void run() { try { Thread.sleep(3000); } catch( InterruptedException e ) { } System.out.println("Saliendo del hilo hijo"); } public static void main( String args[] ){ new ThreadDemo(); try { for ( int i = 5 ; i >0 ; i-- ) { System.out.println(" Seg: " + i ); Thread.sleep(1000); } } catch( InterruptedException e ) { } System.out.println("Saliendo del main"); } } Ambos hilos aguardan utilizando el metodo sleep() de la clase Thread; thDemo tres segundos, y main cinco segundos. Java utilizara los tres segundos de thDemo para ir aguardando los tres primeros segundos del hilo main. Por lo tanto la salida por pantalla al ejecutar el proyecto es: prompt> java ThreadDemo Seg: 5 Seg: 4 Seg: 3 Saliendo del hilo hijo Seg: 2 Seg: 1 Saliendo del hilo main C. Sincronización de threads Mientras la ejecucion de un programa, muchas veces varios procesos han de hacer tareas de una manera sincronizada, actuando en un algun orden. Para ello en Java se emplean la palabra reservada syncronized, en la declaracion de los procesos con este tipo de caracteristicas. Los procesos declarados como syncronized mediante la utilización de excepciones, y de las funciones wait() y notifiy(), respectivamente esperarán a que otro proceso acabe antes de continuar su ejecución. A continuacion se va a ir viendo como implementar el clasico asunto de exclusion mutua conocido como el asunto del productor/consumidor, en el que dos procesos han de alcanzar a una rabo comun, en la que el proceso productor inserta fundamentos en la pila, y el proceso consumidor ha de ir consumiendo los fundamentos en la pila, cada vez que sean insertados: class ColaSincronizada { int n; boolean bandera = false; synchronized int obten() { if ( !bandera ) try wait(); catch( InterruptedException e ); System.out.println( "Obtenido: " + n ); bandera = false; notify(); return n; } synchronized void coloca( int paramN ) { if ( bandera ) try wait(); catch( InterruptedException e ); n = paramN; bandera =true; System.out.println( "Colocado: " + n ); notify(); } } class Productor implements Runnable { ColaSincronizada colaProductor; Productor( ColaSincronizada paramCola ) { colaProductor = paramCola; new Thread( this, "Producer" ).start(); } public void run() { int i = 0; while ( true ) // Bucle infinito colaProductor.coloca( i++ ); } } class Consumidor implements Runnable { ColaSincronizada colaConsumidor; Consumidor( ColaSincronizada paramCola ) { colaConsumidor = paramCola; new Thread( this, "Consumidor" ).start(); } public void run() { while ( true ) // Bucle infinito colaConsumidor.obten( ); } } public static void main( String args[] ) { ColaSincronizada colaLocal = new ColaSincronizada(); new Productor( colaLocal ); new Consumidor( colaLocal ); } La salida del proyecto sera: Colocado: 1 Obtenido: 1 Colocado: 2 Obtenido: 2 Colocado: 3 Obtenido: 3 . . . D. Y mucho más La utilización de programación concurrente y de los hilos de Java con toda su potencia va mucho más allá de los metas de este tutorial. Lo que aquí se ha visto es simplemente una introducción para que el lector sea consciente de cuál es la potencia de este tipo de programación. La utilización de los threads se extiende con métodos para que el programador controle la alternancia de los hilos. Estos métodos son: suspend(); Bloquea temporalmente la ejecución de un hilo. resume(); Activa un hilo bloqueado. stop(); Termina la ejecución de un hilo.