75-62 Técnicas de Programación Concurrentes II Lic. Ing. Osvaldo Clúa 2014 Facultad de Ingeniería Universidad de Buenos Aires Introducción a los Threads Java
Para crear un nuevo Thread Se extiende la clase Thread. Pero esto significa crear un nuevo tipo de Thread. Se implementa la Interface Runnable Que es la forma preferido. Se debe hacer override al método run() 2
Un timer con un tick por segundo public class Timer01 implements Runnable { private int val = 0; boolean sigue = true; Timer01GUI migui; Timer01(Timer01GUI lagui){ migui=lagui; public String tostring(){ return String.valueOf(val); private void inc() { val++; migui.setval(tostring()); public void run() { migui.setid(string.valueof( Thread.currentThread().getId())); while (sigue) { try { Thread.sleep(1000); catch (InterruptedException ex) { ex.printstacktrace(); inc(); 3
Estados de un thread 4
Proyecto Convertir el Timer en un CountDown. Que comience cada instancia en un número distinto. Que se detenga al llegar a cero. 5
java.util.concurrent.executor public interface Executor { void execute(runnable command); Es una abstracción para la ejecución de Threads. Provee soporte para el ciclo de vida de la ejecución, estadísticas, administración y monitoreo. Separa la definición de las Threads de su mecánica de ejecución. 6
java.util.concurrent. ExecutorService Es una Sub Interface de Executor con los métodos para administrar el ciclo de vida. Algunos de sus métodos son: boolean awaittermination(long timeout, TimeUnit unit) boolean isshutdown() boolean isterminated() void shutdown() List<Runnable> shutdownnow() 7
ThreadPoolExecutor implements ExecutorService Administra un pool de threads (worker Threads). Las tareas se toman de una cola. Las threads se reusan en lugar de crear una nueva cada vez. El tamaño del pool puede fijarse. ScheduledThreadPoolExecutor Es una subclase que agrega planificación 8
java.util.concurrent Class Executors Es una Factory para crear objetos que implementan ExecutorService (y otras). static ExecutorService newcachedthreadpool() static ExecutorService newcachedthreadpool(threadfactory threadfactory) Crea los Threads que necesita, pero reusa si hay disponibles static ExecutorService newfixedthreadpool(int nthreads) static ExecutorService newfixedthreadpool(int nthreads, ThreadFactory threadfactory) Crea un pool con un número fijo de Threads 9
Ejemplo Para el CountDown (Timer modificado) ExecutorService eje = Executors.newFixedThreadPool(n / 2); for (int i = 0; i < n; i++) { eje.execute(tick[i]); try { Thread.sleep(duerme); eje.shutdown(); catch (InterruptedException ex) { eje.shutdown(); System.out.println("Se pidió Shutdown"); 10
Ejemplo Reusan el mismo thread Aún son se asignó thread Qué pasó con el Shutdown? Repetir para otra cantidad de timers. Cambiar a shutdownnow() 11
Ejemplo Se usó un CachedThreadPool (observe la repetición del thread 14). Hágalo. 12
Interface Callable<V> V call() throws Exception Se la usa cuando se quiere que un worker thread devuelva un valor (cálculo asincrónico). Interface Future <V> V get() V get(long timeout, TimeUnit unit) boolean isdone() boolean Cancel() boolean iscancelled Representa el resultado del cálculo asincrónico. También se crean con ExecutorService 13
Ejemplo import java.util.concurrent.*; public class TraigoString implements Callable<String> { int duermo = 0; public TraigoString(int n) { duermo = n; @Override public String call() throws Exception { System.out.println("Comienza el calculo de " + duermo + " soy " + Thread.currentThread().getId()); try { Thread.sleep(duermo * 1000); catch (Exception exception) { return ("Devuelto el futuro "+String.valueOf(duermo)); 14
Ejemplo public static void main(string[] args) { int cantthreads = 2; int cantfutures = 6; Future<String> result[] = new Future [cantfutures] ; ExecutorService eje = Executors.newFixedThreadPool(cantThreads); for (int i = 0; i < cantfutures; i++) { result[i] = eje.submit(new TraigoString(i)); for (int i = 1; i < 10; i++) { impterminado(result); //Imprime el resultado de los terminados try { Thread.sleep(i * 1000); // y lo pone en null catch (Exception exception) { if (todasnull(result)) break; //si todos los futuros terminaron System.out.println("Vuelta "+i); System.out.println("Final"); System.exit(0); 15
Obtener el valor futuro con get() public static void impterminada(future<string>[] f) { for (int i = 0; i < f.length; i++) { if ((f[i]!=null) && (f[i].isdone())) { try { System.out.println("Terminada la task " + i + " con el valor <<" + f[i].get()+">>"); catch (InterruptedException ex) { Logger.getLogger(PruebaFuturo.class.getName()).log(Level.SEVERE, null, ex); catch (ExecutionException ex) { Logger.getLogger(PruebaFuturo.class.getName()).log(Level.SEVERE, null, ex); f[i]=null; 16
Salida del Ejemplo Comienza el calculo de 0 soy 10 Comienza el calculo de 1 soy 11 Comienza el calculo de 2 soy 10 Comienza el calculo de 3 soy 11 Vuelta 1 Terminada la task 0 con el valor <<Devuelto el futuro 0>> Terminada la task 1 con el valor <<Devuelto el futuro 1>> Comienza el calculo de 4 soy 10 Vuelta 2 Terminada la task 2 con el valor <<Devuelto el futuro 2>> Comienza el calculo de 5 soy 11 Vuelta 3 Terminada la task 3 con el valor <<Devuelto el futuro 3>> Terminada la task 4 con el valor <<Devuelto el futuro 4>> Vuelta 4 Terminada la task 5 con el valor <<Devuelto el futuro 5>> Final 17
Proyecto Rehacer el Timer con Observador Observable. Un botón de Parcial ( Lap ). Un botón de Start/Stop. Después del Stop, el Start vuelve a comenzar en cero. 18
Proyecto Start Lap Lap + Stop Continue 19