Suscribirse al Feed
28Ene

[código] La interfaz Runnable en Java

En ejemplos anteriores hemos creado clases que heredan de la clase Thread las cuales soportan subprocesamiento múltiple; y sobreescribimos el método run para especificar las tareas a realizar concurrentemente. Sin embargo, puesto que en Java NO existe la herencia múltiple (como en C++) ¿cómo podemos hacer entonces que una clase, que ya hereda de otra distinta a Thread, soporte subprocesamiento múltiple? La respuesta es sencilla: implementar la interfaz Runnable. De hecho la clase Thread implementa a Runnable.

Al implementar la interfaz Runnable en una clase, un objeto puede manipular objetos de esa clase como objetos Runnable. Y tal como cuando heredamos de Thread, debemos declarar y sobrecargar el método run().

Cuando una clase utiliza un objeto Runnable para manipular subprocesos, este crea un objeto Thread y asocia el objeto Runnable con ese objeto Thread (¿enredado? para nada; sigue leyendo y verás que es muy sencillo). La clase Thread posee constructores que pueden recibir objetos Runnable, por ejemplo el constructor

public Thread(Runnable objetoRunnable)

especifica que el método run() del objeto objetoRunnable es el que debe invocarse cuando el subproceso comience a ejecutarse. Por otro lado, el construtor

public Thread(Runnable objetoRunnable, String nombreHilo)

crea un objeto Thread con el nombre nombreHilo, y especifica que el método run() del objeto objetoRunnable es el que debe invocarse cuando el subproceso comience a ejecutarse. ¡Veamos un ejemplo para entender mejor!

Código fuente

El siguiente applet (CaracteresAleatorios.java) demuestra el uso de la interfaz Runnable:


import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class CaracteresAleatorios extends JApplet implements ActionListener {
   private String alfabeto = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   private final static int TAMANIO = 3;
   private JLabel salidas[];
   private JCheckBox casillasVerificacion[];
   private Thread subprocesos[];
   private boolean suspendido[];
   // configurar la GUI y establecer arreglos
   public void init()
   {
      salidas = new JLabel[ TAMANIO ];
      casillasVerificacion = new JCheckBox[ TAMANIO ];
      subprocesos = new Thread[ TAMANIO ];
      suspendido = new boolean[ TAMANIO ];
      Container contenedor = getContentPane();
      contenedor.setLayout( new GridLayout( TAMANIO, 2, 5, 5 ) );
      // crear componentes de la GUI, registrar componentes de escucha y adjuntar
      // componentes al panel de contenido
      for ( int cuenta = 0; cuenta < TAMANIO; cuenta++ ) {
         salidas[ cuenta ] = new JLabel();
         salidas[ cuenta ].setBackground( Color.GREEN );
         salidas[ cuenta ].setOpaque( true );
         contenedor.add( salidas[ cuenta ] );
         casillasVerificacion[ cuenta ] = new JCheckBox( "Suspendido" );
         casillasVerificacion[ cuenta ].addActionListener( this );
         contenedor.add( casillasVerificacion[ cuenta ] );
      }
   } // fin del método init
   // crear e iniciar subprocesos cada vez que se hace una llamada a start (es decir, después de
   // init y cuando el usuario vuelve a visitar la página Web que contiene a este subprograma)
   public void start()
   {
      for ( int cuenta = 0; cuenta < subprocesos.length; cuenta++ ) {

         // crear objeto Thread; inicializar objeto que implementa a Runnable
         subprocesos[ cuenta ] =
            new Thread( new ObjetoRunnable(), "Subproceso " + ( cuenta + 1 ) );

         subprocesos[ cuenta ].start(); // empezar la ejecución del objeto Thread
      }
   }
   // determinar ubicación del subproceso en el arreglo subprocesos
   private int obtenerIndice( Thread actual )
   {
      for ( int cuenta = 0; cuenta < subprocesos.length; cuenta++ )
         if ( actual == subprocesos[ cuenta ] )
            return cuenta;

      return -1;
   }
   // este método se llama cuando el usuario cambia de páginas Web; detiene todos los subprocesos
   public synchronized void stop()
   {
      // establecer referencias en null para terminar el método run de cada subproceso
      for ( int cuenta = 0; cuenta < subprocesos.length; cuenta++ )
         subprocesos[ cuenta ] = null;
      notifyAll(); // notificar a todos los subprocesos en espera, para que puedan terminar
   }
   // manejar eventos de botón
   public synchronized void actionPerformed( ActionEvent evento )
   {
      for ( int cuenta = 0; cuenta < casillasVerificacion.length; cuenta++ ) {
         if ( evento.getSource() == casillasVerificacion[ cuenta ] ) {
            suspendido[ cuenta ] = !suspendido[ cuenta ];
            // cambiar color de la etiqueta al suspender/reanudar
            salidas[ cuenta ].setBackground(
               suspendido[ cuenta ] ? Color.RED : Color.GREEN );
            // si el subproceso se reanudó, asegurarse de que empiece a ejecutarse
            if ( !suspendido[ cuenta ] )
               notifyAll();
            return;
         }
      }
   } // fin del método actionPerformed
   // clase interna privada que implementa a Runnable para controlar los subprocesos
   private class ObjetoRunnable implements Runnable {
      // colocar caracteres aleatorios en la GUI, las variables subprocesoActual e
      // indice son finales, para poder usarlas en una clase interna anónima
      public void run()
      {
         // obtener referencia al subproceso en ejecución
         final Thread subprocesoActual = Thread.currentThread();
         // determinar la posición del subproceso en el arreglo
         final int indice = obtenerIndice( subprocesoActual );
         // la condición del ciclo determina cuándo debe detenerse el subproceso; el ciclo
         // termina cuando la referencia subprocesos[ indice ] se vuelve null
         while ( subprocesos[ indice ] == subprocesoActual ) {
            // estar inactivo de 0 a 1 segundo
            try {
               Thread.sleep( ( int ) ( Math.random() * 1000 ) );
               // determinar si el subproceso debe suspender su ejecución;
               // sincronizar con el objeto de subprograma CaracteresAleatorios
               synchronized( CaracteresAleatorios.this ) {
                  while ( suspendido[ indice ] &amp;&amp;
                     subprocesos[ indice ] == subprocesoActual ) {
                     // suspender temporalmente la ejecución del subproceso
                     CaracteresAleatorios.this.wait();
                  }
               } // fin del bloque synchronized
            } // fin de bloque try
            // si el subproceso se interrumpió durante su espera/inactividad, imprimir el rastreo de la pila
            catch ( InterruptedException excepcion ) {
               excepcion.printStackTrace();
            }
            // mostrar caracter en objeto JLabel correspondiente
            SwingUtilities.invokeLater(
               new Runnable() {
                  // elegir caracter aleatorio y mostrarlo
                  public void run()
                  {
                     char mostrarChar =
                        alfabeto.charAt( ( int ) ( Math.random() * 26 ) );
                     salidas[ indice ].setText(
                        subprocesoActual.getName()  + ": " + mostrarChar );
                  }
               } // fin de la clase interna
            ); // fin de la llamada a SwingUtilities.invokeLater
         } // fin de instrucción while
         System.err.println( subprocesoActual.getName() + " terminando" );
      } // fin del método run
   } // fin de la clase interna privada ObjetoRunnable
} // fin de la clase CaracteresAleatorios

El código del archivo HTML que ejecuta el applet de Java es:


<html>
<applet code="CaracteresAleatorios.class" width=275 height=90>
</applet>
</html>

Descargar código fuente

Etiquetas: , , ,
Los ejercicios utilizados en este post están basados en ejemplos del libro Cómo programar en Java de Deitel, y por lo tanto están bajo la licencia que esta editorial disponga.

3 Comentarios para “[código] La interfaz Runnable en Java”

  1. a gravatar

    modesto vasquez morales dice:  


    gracias por dedicar su tiempo a este noble trabjo, de enseñar a competir en este mundo globalizado.

  2. a gravatar

    modesto vasquez morales dice:  


    gracias,
    por toda la informacion en este portal.

  3. a gravatar

    Lizbeth dice:  


    hola……………..disculpen pero si podrian ayudarme, esq no se como se implmenta un runable con tcp/ip en java..no se si podrina ayudarm porfavor…………….
    gracias…
    su seccion esta bien, por asi entinedes

 

 

Antes de comentar... recuerda que no hago tareas

Te invito a subscribirte al feed RSS. ¿No sabes que es un lector de Feeds?

© 2007 - 2008 Dezinerfolio. Todos los derechos reservados.
Powered by Wordpress. Entradas RSS