• No se han encontrado resultados

Concurrencia en Android LSUB, GYSC, URJC

N/A
N/A
Protected

Academic year: 2021

Share "Concurrencia en Android LSUB, GYSC, URJC"

Copied!
35
0
0

Texto completo

(1)

Concurrencia en

Android

(2)

Repaso de

(3)

Crear un thread

Instanciar un Thread, con el método run

sobreescrito

Intanciar un objeto que cumpla el interfaz

Runnable y pasárselo al constructor de

Thread !

interface Runnable { void run();

(4)

Ejecutar un Thread

Llamar al método start

(5)

Implementando

Runnable

!

public class Biteme implements Runnable {

!

@Override

public void run() {

//Ejecuta en paralelo

} }

!

t = new Thread(new Biteme()); t.start();

b = new Thread(new Biteme()); b.start();

(6)

Heredando de Thread

!

public class Biteme extends Thread {

!

@Override

public void run() {

//Ejecuta en paralelo } } ! t = new Biteme(); t.start(); b = new Biteme(); b.start(); Y se crean

(7)

Heredando de Thread

clase interna

!

public class Cup { public int level;

private class Biteme extends Thread {

@Override

public void run() {

//Ejecuta en paralelo, tiene acceso a Cup

level = 3;

}

public void fill() {

Biteme b = new Biteme();

b.start();

} }

(8)

Heredando de Thread

clase interna anónima

public class Cup { public int level;

public void fill() {

Thread b = new Thread(){

@Override

public void run() {

level = 3; } }; b.start(); } }

(9)

Thread

Thread, metodos de clase interesantes:

currentThread(): referencia al thread actual

activeCount(): numero de threads activos

dumpStack(): pila en stderr

sleep(int ms)

(10)

Executor

java.util.concurrent

Interfaz para ejecutar objetos de tipo

Runnable

Puede hacerlo en serie, en paralelo, con

unos cuantos threads, etc.

!

interface Executor {

public void execute(Runnable r); };

(11)

Executor:

ejemplo de uso

!

SerialExecutor s = new SerialExecutor();

BiteMe b = new BiteMe(); //Runnable

s.execute(b);

(12)

ExecutorService

Es un interfaz que hereda de Executor

Con extras para controlar el progreso

Future<?> submit(Runnable task)

Future tiene un método get() que devuelve

null si ha acabado y otra cosa si no

Future tiene más métodos para controlar

(13)

ExecutorService

!

ExecutorService es = Executors.newFixedThreadPool(3); BiteMe b = new BiteMe(); //Runnable

BiteMe bx = new BiteMe(); //Runnable

Future<?> fut1 = es.submit(b); Future<?> fut2 = es.submit(bx);

!

try{

if(fut1.get() == null){

System.out.println("b ha acabado bien"); }

if(fut2.get() == null){

System.out.println("bx ha acabado bien"); }

}catch(ExecutionException e){

//ha fallado la ejecucion

}catch(InterruptedException e){

//se ha interrumpido

}finally{

es.shutdown(); //acabo con el executor service

(14)

Interrupciones

Son mala idea como método de

comunicación

Mejor comunicarse con variables y que el

thread salga o haga lo que sea el mismo

Pueden ser necesarios si tengo un thread

en sleep

(15)

Condiciones de carrera

Si tengo varios hilos, puedo tener

condiciones de carrera

Ojo con tocar datos compartidos sin

(16)

Sincronización

Puedo esperar que un thread acabe

llamando a su método join() puedo poner

timeout

!

t.start();

(17)

Sincronización

Puedo esperar que todos los threads de un

executor service acaben, tiene timeout:

awaitTermination()

Antes tengo que haber llamado a

shutdown(), “ya no admitas más threads, ve saliendo”

!

(18)

Sincronización:

synchronized

Hay un cierre reentrante asociado a los

objetos (un objeto es un monitor)

Se coge (se entra al monitor) llamando a un

método synchronized o rodeando un bloque

(19)

Sincronización:

synchronized

public class Cup {

public synchronized void fill() {

//Estoy en el monitor de esta instancia de Cup

}

public void fill2() {

BiteMe b = new BiteMe();

synchronized(b){

//Estoy en el monitor b

} }

(20)

Sincronización:

synchronized

public class Cup {

public synchronized void fill() {

//Estoy en el monitor de esta instancia de Cup

}

public void fill2() {

synchronized(this){

//Estoy en el monitor de esta instancia de Cup

} }

(21)

Sincronización:

synchronized

public class Cup {

public static synchronized void fill3() {

//Estoy en el monitor de la clase Cup

} }

Ojo, los métodos estáticos cogen el

cierre de la clase

(22)

Sincronización:

synchronized

public class Cup {

public synchronized void fill() {

//Estoy en el monitor de esta instancia de Cup

}

public synchronized void fill2() {

fill(); //No hay deadlock, es un monitor

} }

(23)

Sincronización:

comunicación

BlockingQueue: FIFOs bloqueantes, como

canales

ConcurrentMap: Diccionario

(24)

Sincronización

Decorador sincronizado para colecciones (hay

otros especializados):

public static <T> Collection<T> synchronizedCollection(Collection<T> c)

Ojo, hay que sincronizar el acceso

!

Collection c = Collections.synchronizedCollection(myCollection); ...

synchronized(c) {

Iterator i = c.iterator(); // Ojo, dentro de un bloque synchronized

while (i.hasNext()) foo(i.next()); }

(25)

Concurrencia en

Android

(26)

Problemas

GUI no responde: las callbacks no pueden

estar mucho rato bloqueadas; usar threads

Threads en background no pueden

(27)

Alternativas

Crear threads, esperar a que acaben,

actualizar la GUI, join() o awaitTermination()

Usar View.post para actualizar la GUI

Usar AsyncTask, divide tareas entre threads

en background y threads de GUI

No actualizo la GUI si no estoy en el hilo

(28)

View.post

Tengo un hilo que he creado corriendo en

background

Quiero que cambie la UI

Por ejemplo una barra de progreso

Uso el método post para pasarle un

Runnable que ejecutará el hilo asociado al

(29)

Ejemplo:

Botón para un tono:

public class Tono implements OnClickListener { View but; void playSound(){ //suena } Tono(View v) { but = v; //inicializo el tono }

private class Pressme implements Runnable {

boolean p; View v;

Pressme(View b, boolean pressed){

p = pressed;

v = b; }

@Override

public void run() {

v.setEnabled(!p); }

(30)

Ejemplo:

Botón para un tono:

!

@Override

public void onClick(View arg0) {

arg0.setEnabled(false);

Thread t = new Thread(){

public void run(){

playSound();

try{

Thread.sleep(3*1000);

}catch(InterruptedException e){}

but.post(new Pressme(but, false));

}

};

t.start(); }

(31)

Ejemplo: OJO

El hilo tiene una referencia al botón

Que vive en la Activity

¿Qué sucede si la Activity se recrea?

Por ejemplo, si giran la pantalla…

(32)

AsyncTask

Crea un hilo cuando se llama al método

execute()

Ejecuta algunos métodos en el contexto de

ese hilo

Y otros en el contexto de la GUI (son

(33)

AsyncTask

private class SomeTask extends AsyncTask<Type1, Type2, Type3> { public Type3 doInBackground(Type1... params) {

return(doNonUiStuffWith(params)); }

public void onPostExecute(Type2 result) {

doUiStuff(result); }

} …

new SomeTask().execute(type1VarA, type1VarB);

(34)

AsyncTask

Los tres parámetros del tipo genérico:

AsyncTask<Type1, Type2, Type3>

Type1 Parámetros de

doInBackground(Type1...)

Type 2 registro de progreso

onProgressUpdate(Type2...)

Type 3 resultado de Type3 doInBackground(Type1 ...)

(35)

AsyncTask

doInbackground() ejecuta en un hilo en background

onPreExecute() onPostExecute() ejecutan en GUI antes y después del hilo

onProgressUpdate() lo ejecuta el GUI, cuando se ha llamado a publishProgress()

El argumento de onProgressUpdate() es lo que

Referencias

Documento similar