Descarga la aplicación para disfrutar aún más
Vista previa del material en texto
CLASE 13 MODELO DE DESARROLLO DE PROGRAMAS Y PROGRAMACION CONCURRENTE FAC.DE INGENIERIA - UNJu INTERFAZ RUNNABLE IMPLEMENTACIÓN DE HILOS USANDO LA INTERFAZ RUNNABLE 1 interfaz solamente puede contener métodos abstractos y/o variables estáticas y finales (constantes). Las clases pueden implementar métodos y contener variables q no sean constantes. 1 interfaz no puede implementar cualquier método. 1 clase q implemente 1interfaz debe implementar todos los métodos definidos en esa interfaz. 1 interfaz tiene la posibilidad de poder extenderse de otras interfaces y, al contrario que las clases, puede extenderse de múltiples interfaces. 1 interfaz no puede ser instanciada con el operador new. Es la técnica+adecuada p/la creación de aplicac.multitarea en lugar de 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. Florencia Resaltado Florencia Resaltado Florencia Resaltado IMPLEMENTACIÓN DE HILOS USANDO LA INTERFAZ RUNNABLE La interfaz Runnable debe ser implementada x cualquier clase cuyas instancias sean ejecutadas x 1 hilo. Dicha clase debe implementar el método 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 de haberse creado 1clase q implemente la interfaz Runnable se requiere crear un objeto del tipo Thread dentro de esa clase, usando cualquiera de los constructores de Thread. Florencia Resaltado Florencia Resaltado Florencia Resaltado Florencia Resaltado 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étodo run(), q deba incluir las acciones a realizar x las tareas. Al codificar este método mediante la implementación de la interfaz Runnable permite a la clase heredar al mismo tiempo la funcionalidad de alguna otra clase existente. Código de 1clase p/la impresión de los nombres de los thread implementando la interfaz 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 un objeto 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) //Se crea 1único objeto 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 de 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étodo run() de la clase q implementa a Runnable(). P/crear objetos Thread con estas características, se debe usar alguno de los siguientes constructores de 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étodos de la cajera1 y después los métodos de la cajera2. A nivel de procesamiento es como tener 1 sola cajera. A continuación se implementa el método 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 se ejecuta este ej.se observa cómo se procesa 1ro.la compra del cliente 1 y después la compra del cliente 2 tardando en procesar ambas compras un tiempo de 26 segundos. CLASE “CAJERATHREAD.JAVA“ public classCajeraThread 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 + " HA TERMINADO 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 que 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étodo “run()” se va a ejecutar de 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 }); // Tiempo inicial de referencia long initialTime = System.currentTimeMillis(); CajeraThread cajera1 = new CajeraThread("Cajera 1", cliente1, initialTime); CajeraThread cajera2 = new CajeraThread("Cajera 2", cliente2, initialTime); cajera1.start(); cajera2.start(); } } El método 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 dispondrá ni se podrá sobre-escribir los métodos de la clase Thread ya q no se van a utilizar y solo se va a tener q sobre- escribir el método “run()“. Solo será necesario implementar el método “run()” p/q los procesos implementados en ese método se ejecuten en un hilo 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
Compartir