Logo Studenta

Tema 15 Clase 15 - Runnable

¡Este material tiene más páginas!

Vista previa del material en texto

CLASE 15 – 2.019
MODELO DE DESARROLLO DE PROGRAMAS Y PROGRAMACION 
CONCURRENTE
FAC.DE INGENIERIA - UNJu
INTERFAZ RUNNABLE
IMPLEMENTACIÓN DE HILOS USANDO LA INTERFAZ RUNNABLE
1 interfaz solo puede contener mét.abstr.y/o variables estáticas y finales (constantes). 
Las clases pueden implementar mét.y contener variables q no sean constantes. 
1 interfaz no puede implementar cualquier método. 
1clase q implem.1interfaz debe implementar todos los mét.definidos en esa interfaz. 
1 interfaz tiene la posibilidad d poder extenderse de otras interf.y, al contrario q las 
clases, puede extenderse d múltiples interf.,1 interfaz no puede ser instanciada con el 
operador new.
Es la técn+adecuada p/la creación de aplicac.multitarea en lugar d la extens.de la 
clase Thread. 
Acciones:
o Implementar el método run() de la interfaz Runnable.
o Creación y ejecución de tareas.
IMPLEMENTACIÓN DE HILOS USANDO LA INTERFAZ RUNNABLE
La interfaz Runnable debe ser implement.x cualquier clase cuyas instancias 
sean ejecutadas x 1 hilo. Dicha clase debe implementar el mét.run().
La implementación de la interfaz Runnable es la forma + habitual de crear 
tareas, ya q proporciona al desarrollador 1forma p/agrupar el trabajo de 
infraestructura de la clase. La interfaz establece el trabajo a realizar y la clase 
o clases q la implementan, indican cómo realizar ese trabajo, se puede 
construir 1hilo sobre cualquier objeto q implemente la interfaz Runnable.
P/implementar esta interfaz, 1clase solo tiene q implementar el método run(). 
Dentro del run() se define el código q constituye el nuevo hilo. Después d 
haberse creado 1clase q implemente la interfaz Runnable s requiere crear1 
objeto del tipo Thread dentro de esa clase, usando cualquiera de los 
constructores de Thread.
IMPLEMENT.DE HILOS USANDO LA INTERFAZ RUNNABLE - ESQUEMA
// crear una clase con hilos
public class MiClase implements Runnable {
Thread unHilo;
MiClase() {
unHilo = new Thread();
}
public void run() {
if (unHilo != null) {
//cuerpo del hilo
}
}
}
La sig.forma gral.crea el hilo 
e inicia su ejecución en la 
clase q usa a MiClase:
MiClase miHilo = new MiClase ();
new Thread (miHilo).start();
IMPLEMENTACIÓN DEL MÉTODO RUN()
public class TareaRb implements Runnable
{public void run()
{for (int i=1; i<=100; i++)
{System.out.println("Nombre " + Thread.currentThread().getName());
try { Thread.sleep(100); }
catch (InterruptedException e) { e.printStackTrace(); } } } }
La interfaz Runnable incluye 1único mét.run() con las acciones a realizar x las tareas.
Al codificar este mét.mediante la implementación d la interfaz Runnable permite a la 
clase heredar al mismo tiempo la funcionalidad de alguna otra clase existente.
Código d1clase p/la impresión d los nombres d los thread implement.la interf. Runnable:
Al no heredar de Thread, no dispone de 1 constructor al q pasarle el nombre de la 
tarea; lo q se debe analizar es xq el método getName() devuelve el nombre de la 
tarea en ejecución. La respuesta es q la llamada a currentThread() no devuelve 
1objeto TareaRb sino 1 objeto de la clase Thread q representa la tarea en ejecución.
CREACIÓN Y EJECUCIÓN DE TAREAS
public class Principal
{public static void main (String [] args)
//S crea 1único obj. tarearb q se comparte en c/thread
{TareaRb t = new TareaRb();
// Las tareas son instancias de la clase Thread
Thread t1 = new Thread(t,"pepe");
Thread t2 = new Thread(t,"ana");
Thread t3 = new Thread(t,"juan");
// Los Threads se ponen en ejecución
t1.start();
t2.start();
t3.start(); } }
Toda tarea es 1thread o sea q habrá 
q crear tantos objetos d la clase 
Thread como tareas se quieran 
poner en ejecución, el tema es q el 
código asociado a esas tareas debe 
ser el q está definido en el mét.run() 
d la clase q implem.a Runnable().
P/crear objetos Thread con estas 
carácter., s debe usar alguno d los 
sig.constructores d la clase Thread:
Thread(Runnable obj)
Thread (Runnable obj, String nombre)
En ambos casos, la creación y 
ejecución de las tareas en el ej.de la 
impresión de nombres quedaría :
EJEMPLOS SIN HILOS, CON THREAD Y CON INTERFAZ RUNNABLE
Se simula el proceso de cobro de un supermercado; donde:
• Los clientes adquieren productos
• 1cajera cobra los productos, pasándolos 1 a 1 x el escáner de la caja 
registradora. La cajera debe procesar la compra cliente a cliente, 1ro. le cobra 
al cliente 1, luego al cliente 2 y así sucesivamente. 
Se define 1 clase “Cajera” y una clase “Cliente” el cual tendrá un “array de enteros” 
q representa los productos q se compraron y el tiempo q la cajera tarda en pasar el 
producto x el escáner.
X ej. si se tiene 1 array con [1,3,5] significa q el cliente ha comprado 3 productos y q 
la cajera tarda en procesar al producto 1 ‘1 segundo’, al producto 2 ‘3 segundos’ y 
al producto 3 ‘5 segundos’, con lo cual se tarda en cobrar al cliente x toda su 
compra ‘9 segundos’.
CLASE “CAJERA.JAVA“
public class Cajera {
private String nombre;
public Cajera(String nombre) {
super();
this.nombre = nombre; }
public void procesarCompra (Cliente cliente, long timeStamp) {
System.out.println("La cajera " + this.nombre
+ " COMIENZA A PROCESAR LA COMPRA DEL CLIENTE "+ cliente.getNombre() 
+ " EN EL TIEMPO: “ + (System.currentTimeMillis() - timeStamp) / 1000 + "seg");
for (int i = 0; i < cliente.getCarroCompra().length; i++) {
this.esperarXsegundos(cliente.getCarroCompra()[i]);
System.out.println("Procesado el producto " + (i + 1)
+ " ->Tiempo: " + (System.currentTimeMillis() - timeStamp) / 1000 + "seg"); }
System.out.println("La cajera " + this.nombre
+ " HA TERMINADO DE PROCESAR " + cliente.getNombre() + " EN EL TIEMPO: " 
+ (System.currentTimeMillis() - timeStamp) / 1000 + "seg"); }
private void esperarXsegundos (int segundos) {
try { Thread.sleep(segundos * 1000);
} catch (InterruptedException ex) {
Thread.currentThread().interrupt(); } } }
CLASE “CLIENTE.JAVA”
public class Cliente {
private String nombre;
private int[] carroCompra;
public Cliente(String nombre, 
int[] carroCompra) {
super();
this.nombre = nombre;
this.carroCompra = carroCompra; }
public String getNombre() {
return nombre; }
public void setNombre(String nombre) {
this.nombre = nombre; }
public int[] getCarroCompra() {
return carroCompra; }
public void setCarroCompra(int[] 
carroCompra) {
this.carroCompra = carroCompra; } }
Si se ejecuta este programa con 2 
Clientes y 1solo proceso (q es lo q se 
suele hacer normalmente), se procesa 
1ro.la compra del Cliente 1 y después 
la del Cliente 2, con lo cual se tarda el 
tiempo del Cliente 1 + Cliente 2. 
CUIDADO: Aunq se haya puesto 2
objetos de la clase Cajera (cajera1 y 
cajera2) no significa tener 2cajeras 
independientes, lo q se afirma es q 
dentro del mismo hilo se ejecutan 
1ro.los mét.d la cajera1 y después los 
mét.d la cajera2. A nivel de 
procesam.es como tener 1 sola cajera.
A continuac.se implementa el mét. 
Main para lanzar el programa.
CLASE “MAIN.JAVA“
public class Main {
public static void main(String[] args) {
Cliente cliente1 = new Cliente("Cliente 1", new int[] { 2, 2, 1, 5, 2, 3 });
Cliente cliente2 = new Cliente("Cliente 2", new int[] { 1, 3, 5, 1, 1 });
Cajera cajera1 = new Cajera("Cajera 1");
Cajera cajera2 = new Cajera("Cajera 2");
// Tiempo inicial de referencia
long initialTime = System.currentTimeMillis();
cajera1.procesarCompra(cliente1, initialTime); 
cajera2.procesarCompra(cliente2, initialTime); } }
Si s ejecuta este ej.se observa cómo s procesa 1ro.la compra del cliente 1 y después 
la compra del cliente 2 tardando en procesar ambas compras un tiempo de 26 seg.
CLASE “CAJERATHREAD.JAVA“
public class CajeraThread extends Thread {
private String nombre;
private Cliente cliente;
private long initialTime;
// Constructor, getter & setter
public CajeraThread(String nombre, Cliente cliente, long initialTime) {
super();
this.nombre = nombre;
this.cliente = cliente;this.initialTime = initialTime; }
Se pueden procesar 2clientes a la vez si hubiese 2cajeras y se asigna 
1a c/cliente. P/ello se modifica la clase “Cajera.java” haciendo q 
herede de la clase Thread p/heredar y sobre-escribiendo algunos de 
sus métodos. 1ro.se codifica la clase “CajeraThread.java” y después se 
explican sus características.
La clase 
“CajeraThread” hereda 
de la clase Thread
CLASE “CAJERATHREAD.JAVA“@Override
public void run() {
System.out.println("La cajera “+this.nombre+ " COMIENZA A PROCESAR LA COMPRA DEL CLIENTE " 
+this.cliente.getNombre()+" EN EL TIEMPO: "+(System.currentTimeMillis() -
this.initialTime)/1000+"seg");
for (int i = 0; i < this.cliente.getCarroCompra().length; i++) { 
this.esperarXsegundos(cliente.getCarroCompra()[i]); 
System.out.println("Procesado el producto " + (i + 1) + " del cliente " + this.cliente.getNombre() 
+ "->Tiempo: " + (System.currentTimeMillis() - this.initialTime) / 1000 + "seg"); }
System.out.println("La cajera "+this.nombre+" TERMINO DE PROCESAR"+this.cliente.getNombre() 
+ " EN EL TIEMPO: " + (System.currentTimeMillis() - this.initialTime) / 1000 + "seg"); }
private void esperarXsegundos(int segundos) {
try { Thread.sleep(segundos * 1000); } catch (InterruptedException ex) {
Thread.currentThread().interrupt(); } } }
Es imprescindible sobre-escribir el método “run()” (de ahí la etiqueta @Override) , ya q es un 
método q está en la clase Runnable y la clase Thread Implementa esa Interfaz, y xq en él se 
codifica la funcionalidad q se ejecuta en 1hilo; es decir, q lo q se programe en el mét.“run()” se 
va a ejecutar d forma secuencial en 1 hilo. En la clase “CajeraThread” se pueden sobre-escribir 
más métodos p/q hagan acciones sobre el hilo o thread como x ej., parar el thread, ponerlo en 
reposo, etc
CLASE “MAINTHREAD.JAVA“public class MainThread {
public static void main(String[] args) {
Cliente cliente1 = new Cliente("Cliente 1", new int[] { 2, 2, 1, 5, 2, 3 });
Cliente cliente2 = new Cliente("Cliente 2", new int[] { 1, 3, 5, 1, 1 });
long initialTime = System.currentTimeMillis(); // Tiempo inicial de referencia
CajeraThread cajera1 = new CajeraThread("Cajera 1", cliente1, initialTime);
CajeraThread cajera2 = new CajeraThread("Cajera 2", cliente2, initialTime);
cajera1.start();
cajera2.start(); } }
El mét.Main de la clase “MainThread.java” procesa las compras de los clientes de 
forma paralela e independiente, y tarda solo 15 segundos en terminar su ejecución. 
CLASE “MAINTHREAD.JAVA“
public class MainRunnable implements Runnable{
private Cliente cliente;
private Cajera cajera;
private long initialTime;
public MainRunnable (Cliente cliente, Cajera cajera, long initialTime){
this.cajera = cajera;
this.cliente = cliente;
this.initialTime = initialTime;}
public static void main(String[] args) {
Cliente cliente1 = new Cliente("Cliente 1", new int[] { 2, 2, 1, 5, 2, 3 });
Cliente cliente2 = new Cliente("Cliente 2", new int[] { 1, 3, 5, 1, 1 });
Cajera cajera1 = new Cajera("Cajera 1");
Cajera cajera2 = new Cajera("Cajera 2");
// Tiempo inicial de referencia
long initialTime = System.currentTimeMillis();
Runnable proceso1 = new MainRunnable(cliente1, cajera1, initialTime);
Runnable proceso2 = new MainRunnable(cliente2, cajera2, initialTime);
new Thread(proceso1).start();
new Thread(proceso2).start(); }
@Override
public void run() {
this.cajera.procesarCompra(this.cliente, this.initialTime); } }
Otra forma es 
implementar la 
Interfaz “Runnable”. 
En este caso no se 
dispone ni se podrá 
sobre-escribir los mét. 
d la clase Thread ya q 
no s van a usar y solo 
s va a tener q sobre-
escribir el mét.“run()“. 
Solo es necesario 
implementar el mét. 
“run()” p/q los 
procesos implement. 
en ese mét.s ejecuten 
en 1hilo diferente. En 
este ej. se utiliza 
objetos de las clases 
“Cliente.java” y 
“Cajera.java” p/ 
implementar la 
multitarea.
• García de Jalón J, Rodríguez J, Mingo I, Imaz A, Brazalez A, Larzabal A, 
Calleja J y García J. 2.000. Aprenda Java como si estuviera en primero.
• Página web consultada, accedidas en Septiembre de 2.018: 
o http://jarroba.com/multitarea-e-hilos-en-java-con-ejemplos-thread-
runnable/
• Sánchez Jorge. 2.004. Java2 incluye Swing, Threads, programación en 
red, Javabeans, JDBC y JSP / Servlets.
BIBLIOGRAFÍA RECOMENDADA

Continuar navegando