[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 ] &&
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>









modesto vasquez morales dice:
Abril 16th, 2008 a las 10:34 pm
gracias por dedicar su tiempo a este noble trabjo, de enseñar a competir en este mundo globalizado.
modesto vasquez morales dice:
Abril 16th, 2008 a las 10:36 pm
gracias,
por toda la informacion en este portal.
Lizbeth dice:
Abril 27th, 2008 a las 11:48 am
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