java scjp clase9

Upload: raul-oramas-bustillos

Post on 07-Jul-2018

236 views

Category:

Documents


0 download

TRANSCRIPT

  • 8/18/2019 Java SCJP clase9

    1/40

    SCJP 6Clase 9 – Threads

    Ezequiel Aranda

    Sun Microsystems Campus

    Ambassador

  • 8/18/2019 Java SCJP clase9

    2/40

    Disclaimer & Acknowledgments

    > Even though Ezequiel Aranda is a full-time employee of Sun

    Microsystems, the contents here are created as his own

    personal endeavor and thus does not reflect any official

    stance of Sun Microsystems.

    Sun Microsystems is not responsible for any inaccuracies inthe contents.

    Acknowledgments – The slides of this presentation are made

    from “SCJP Unit 9” by Warit Wanwithu and Thanisa

    Kruawaisayawan and SCJP Workshop by P. Srikanth.

    This slides are Licensed under a Creative Commons

    Attribution – Noncommercial – Share Alike 3.0

    > http://creativecommons.org/licenses/by-nc-sa/3.0/

  • 8/18/2019 Java SCJP clase9

    3/40

     AGENDA

    > java.lang.Thread

    > java.lang.Runnable

    > Instanciación e inicialización

    de hilos

    > Planificación

    > Estados de los hilos

    Sincronización, locks ydeadlocks

    > Interacción entre hilos

  • 8/18/2019 Java SCJP clase9

    4/40

    Extendiendo java.lang.Thread

    > Sobrescribir el método run(). Debería ser algo

    así:

    class MyThread extends Thread {

     public void run() {

    System.out.println("Important

    job running in MyThread"); } } 

    La limitación de este enfoque es que alextender Thread, no podremos extender

    ninguna otra clase.

  • 8/18/2019 Java SCJP clase9

    5/40

    Extendiendo java.lang.Thread (II)

    > Podemos también sobrecargar el método run():

    class MyThread extends Thread {

     public void run() {

    System.out.println("Important jobrunning in MyThread"); }

     public void run(String s) {

    System.out.println("String in run is "

    + s); } }

    Sin embargo, dicho método será ignorado por la

    clase Thread salvo que lo llamemos nosotros

    mismos y será ejecutado como un método normal.

  • 8/18/2019 Java SCJP clase9

    6/40

    Implementando java.lang.Runnable

    > Implementando Runnable podremos,

    adicionalmente, extender de otra clase.

    class MyRunnable implements Runnable{

     public void run() {

    System.out.println("Important

    job running in MyRunnable");

    }

  • 8/18/2019 Java SCJP clase9

    7/40

    Instanciando un Thread

    > Si extendemos la clase Thread:

     MyThread t = new MyThread()

    > Si implementamos la interfaz Runnable,

    también necesitaremos una instancia de

    Thread:

     MyRunnable r = new MyRunnable();

    Thread t = new Thread(r); 

    > Suele pensarse en Thread como el “obrero” y

    Runnable como el “trabajo”.

  • 8/18/2019 Java SCJP clase9

    8/40

    Instaciando un thread (II)

    > Existen varios constructores en la clase

    Thread:

    Thread()

    Thread(Runnable target> Thread(Runnable target, String name)

    Thread(String name)

  • 8/18/2019 Java SCJP clase9

    9/40

    Inicializando un Thread

    t.start();

    > ¿Y que pasa cuando llamamos a start()?

    Se inicializa un nuevo hilo de ejecución (con su

    stack de llamadas propio).

    El estado de dicho hilo pasa de “new” a

    “runnable”.

    > Cuando se le de la posibilidad de ejecutarse, se

    ejecutará su método run().

  • 8/18/2019 Java SCJP clase9

    10/40

    Inicializando un Thread: Aclaraciones

    > Llamar explicitamente a un método run() solo

    hará que se invoque al método run() del hilo

    que se encuentra en ejecución actualmente.

    El siguiente código no inicializa un nuevo hilode ejecución (aunque es código legal):

    Runnable r = new Runnable();

    r.run();

  • 8/18/2019 Java SCJP clase9

    11/40

    El planificador de threads

    El orden en el cual se ejecutará un conjunto

    de threads no está garantizado. 

    class NameRunnable implements Runnable {

     public void run() {for (int x = 1; x

  • 8/18/2019 Java SCJP clase9

    12/40

    Estados de un Thread

    > New: es el estado en el que se encuentra el

    hilo apenas después de su creación. En este

    punto no se considera que el hilo este “vivo”.

    Runnable: que un hilo se encuentre en esteestado significa que es elegible para su

    ejecución, pero el planificador aún no lo ha

    seleccionado. En este punto se considera que

    el hilo esta vivo.

  • 8/18/2019 Java SCJP clase9

    13/40

    Estados de un Thread (II)

    > Running: que un hilo esté en este estado

    significa que el planificador lo ha

    seleccionado para ser el hilo en ejecución.

    Waiting/ Blocked/ Sleeping: en cualquiera deestos estados, el hilo está vivo, pero no es

    elegible para ejecución. Puede volver al

    estado runnable en cualquier momento.

  • 8/18/2019 Java SCJP clase9

    14/40

    Estados de un Thread (III)

    t.sleep() o t.yield() 

    > Se encuentran definidas para afectar al hilo

    que se encuentra en ejecución.

    Debemos recordar que un hilo bloqueado se

    considera vivo aún.

  • 8/18/2019 Java SCJP clase9

    15/40

    Estados de un Thread (IV)

    > Dead: una vez que el hilo ha muerto, no

    puede revivirse. Invocar start() en un thread

    muerto resultará en una exception.

    NEW

    WAITING

    o

    BLOCKED

    RUNNABLE  RUNNING  DEAD

  • 8/18/2019 Java SCJP clase9

    16/40

    Sleeping

    > sleep() es un método estático de la clase

    Thread.

    > Se usa para frenar a un hilo forzandolo a ir al

    estado “sleeping” por una fracción de tiempodada antes de volver a ser elegible para

    ejecución.try {

    Thread.sleep(20*60*1000); //powernap

    }

    catch (InterruptedException ex) { } 

  • 8/18/2019 Java SCJP clase9

    17/40

    Sleeping (II)

    class NameRunnable implements Runnable {

     public void run() {

    for (int x = 1; x < 4; x++) {

    System.out.println("Run by "+

    Thread.currentThread().getName());try {Thread.sleep(1000); }

    catch (InterruptedException ex) { }

    }

    }}

    > Sleep es una forma de dar a todos los hilos la

    posibilidad de ejecutarse. 

  • 8/18/2019 Java SCJP clase9

    18/40

     yield()

    > La idea de yield() es la de cambiar el estado

    del hilo en ejecución a runnable, dandole así

    la posibilidad de ejecutarse a otros hilos de la

    misma prioridad.> Sin embargo, nada prohíbe al planificador

    volver a seleccionar para ejecución al mismo

    hilo una y otra vez.

  • 8/18/2019 Java SCJP clase9

    19/40

    join()

    > Si un hilo B necesita que la tarea de un hilo A

    se complete para poder comenzar su

    ejecución, necesitamos hacer un “join” entre

    B y A.> Esto hará que B no pueda pasar al estado

    runnable hasta que A complete su ejecución y

    pase al estado dead.

  • 8/18/2019 Java SCJP clase9

    20/40

    join() (II)

  • 8/18/2019 Java SCJP clase9

    21/40

    En resumen…

    > sleep(): garantiza que el hilo en ejecución

    pase al estado “sleeping” por al menos el

    tiempo especificado.

     yield(): no garantiza absolutamente nada. Sufunción es la de volver al hilo en ejecución al

    estado “runnable”.

    join(): provoca que se detenga la ejecución

    del hilo actual hasta, por lo menos, la

    finalización del hilo con el que se realizó el

    join.

  • 8/18/2019 Java SCJP clase9

    22/40

    Sincronización

    > Existe un problema conocido como “race condition”

    Se da cuando múltiples hilos que pueden acceder a un

    mismo recurso.

    Produce datos corruptos cuando los hilos acceden al valor

    de los datos entremedio de operaciones que deberían seratómicas.

  • 8/18/2019 Java SCJP clase9

    23/40

    Sincronización(II)

    > No hay forma de garantizar que un mismo

    hilo se mantendrá en ejecución durante toda

    la operación atómica.

    Pero sí es posible garantizar que incluso si elhilo no se mantiene en ejecución durante la

    operación atómica, ningún otro hilo pueda

    actuar sobre los mismos datos.

  • 8/18/2019 Java SCJP clase9

    24/40

    Sincronización (III)

    > Entonces… ¿Cómo protegemos nuestros

    datos?

    > Debemos hacer dos cosas

    Hacer privadas a las variables

    > Sincronizar el código que modifica las variables.

    (utilizando la palabra reservada synchronized).

    > Ejemplo:

     private synchronized void

     makeWithdrawal(int amt)

  • 8/18/2019 Java SCJP clase9

    25/40

    Sincronización y locks

    > Cada objeto en java tiene un lock, que se

    utiliza cuando el mismo tiene código marcado

    como synchronized en alguno de sus

    métodos.> Cuando ingresamos en un método

    sincronizado, no estático, obtenemos

    automáticamente el lock de la instancia de la

    clase cuyo código estamos ejecutando.

  • 8/18/2019 Java SCJP clase9

    26/40

    Sincronización y locks (II)

    Dado que cada objeto solo tiene un lock, si un

    hilo ha obtenido dicho lock, ningún otro hilo

    podrá obtenerlo hasta que el primero lo

    libere.> Si una clase tiene métodos sincronizados y

    métodos no sincronizados, múltiples hilos

    pueden aún acceder a los métodos no

    sincronizados.

    Cuando un hilo pasa a estar “dormido”,

    retiene todos sus locks.

  • 8/18/2019 Java SCJP clase9

    27/40

    Sincronización y locks (III)

    Se puede reducir el tamaño de las partes

    sincronizadas a un bloque (en vez de un método

    completo).

    En una muestra de originalidad propia del equipo de

    diseño de Stacy Malibú, esto se bautizó “bloque

    sincronizado”.class SyncTest {

     public void doStuff() {

    System.out.println("not synchronized");

    synchronized(this) {

    System.out.println("synchronized"); } } } 

  • 8/18/2019 Java SCJP clase9

    28/40

    Sincronización y locks (IV)

     public synchronized void doStuff() {

    System.out.println("synchronized");

    Es equivalente a: public void doStuff() {

    synchronized(this) {

    System.out.println("synchronized");

    }

  • 8/18/2019 Java SCJP clase9

    29/40

    Métodos estáticos sincronizados

    Sólo hay una copia de los datos estáticos, por

    lo que hará falta un lock para la clase

    completa para sincronizar métodos estáticos.

     public static int getCount() {

    synchronized(MyClass.class) {

    return count;

    }} 

  • 8/18/2019 Java SCJP clase9

    30/40

    ¿Qué sucede si un hilo no puede

    obtener un lock?

    Básicamente, el hilo va a parar a una especie

    de pool para dicho lock, en donde esperará a

    que se libere el lock y el hilo pueda volver al

    estado runnable.> Al liberarse un lock, no hay forma de

    garantizar que un hilo en particular sea el

    que lo obtenga a continuación.

    Ni siquiera hay forma de garantizar que el hilo

    que espero por más tiempo sea el que lo obtenga.

  • 8/18/2019 Java SCJP clase9

    31/40

    ¿Qué sucede si un hilo no puede

    obtener un lock? (II)>

     

    Dos hilos que llaman a métodos

    sincronizados, no estáticos de la misma clase

    solo se bloquearan uno al otro si se invocan

    sobre la misma instancia. En caso contrarioobtendrán un lock cada uno.

    En el caso de los métodos estáticos, los hilos

    siempre competirán por el mismo lock.

    Un método estático y uno no estático no se

    bloquearán uno al otro, nunca.

  • 8/18/2019 Java SCJP clase9

    32/40

    ¿Qué sucede si un hilo no puede

    obtener un lock? (III)>

     

    Para los bloques sincronizados, debemos fijarnos en

    cual fue el objeto utilizado en el cerrojo (dentro de

    los paréntesis que se encuentran luego de la palabra

    synchronized).

    Los hilos que utilizan el mismo objeto se bloquearán

    entre ellos. Los que utilizan distintos objetos, no.

  • 8/18/2019 Java SCJP clase9

    33/40

    Entonces, ¿cuándo necesito

    sincronizar?>

     

    Simple: cuando un método que será usado

    por varios hilos accede a valores

    modificables.

    El acceso a campos estáticos debe ser hechodesde métodos estáticos sincronizados.

    > El acceso a campos no estáticos sincronizados

    debe ser hecho desde métodos no estáticos

    sincronizados.

  • 8/18/2019 Java SCJP clase9

    34/40

    “Thread Safe”

    Cuando los métodos de una clase han sido

    cuidadosamente sincronizados para proteger

    los datos de la misma, llamamos a esa clase

    “Thread Safe”.> Por ejemplo los métodos de StringBuffer se

    encuentran sincronizados, mientras que los

    de StringBuilder no lo están. Esto hace que en

    un ambiente multithread sea más seguroutilizar StringBuffer.

  • 8/18/2019 Java SCJP clase9

    35/40

    Deadlock

    Un deadlock ocurre cuando dos hilos se

    bloquean mutuamente esperando que el otro

    libere el lock que cada uno necesita.

    Ninguno puede

    continuar su ejecución

    hasta que el otro libere

    el lock por el queespera, por lo que se

    sientan a esperar para

    siempre…

  • 8/18/2019 Java SCJP clase9

    36/40

    Interacción entre hilos

    La clase Object tiene tres métodos: wait(),

    notify() y notifyAll(), que ayudan a los hilos a

    comunicar el estado de los eventos que les

    interesan.> Un punto clave para el examen es recordar

    que cualquiera de estos métodos debe ser

    llamado desde un contexto sincronizado. Un

    hilo no puede invocar wait o notify en unobjeto salvo que posea el lock de dicho

    objeto.

  • 8/18/2019 Java SCJP clase9

    37/40

    class ThreadA {

     public static void main(String [] args) {

    ThreadB b = new ThreadB();

     b.start();synchronized(b) {

    try {

    System.out.println("Waiting for b

    to complete..."); b.wait();

    }

    catch (InterruptedException e) {}

    System.out.println("Total is:

    " + b.total);

    }

    }

  • 8/18/2019 Java SCJP clase9

    38/40

    class ThreadB extends Thread {

    int total;

     public void run() {

    synchronized(this) {

    for(int i=0;i

  • 8/18/2019 Java SCJP clase9

    39/40

    Usando notifyAll() cuando varios hilos

    están esperando

    Podemos utilizar notifyAll() en el objeto para

    permitir que todos los hilos salgan del área de

    espera y vuelvan al estado runnable.

    De esta forma nos aseguramos que el threadcorrecto (junto con todos los otros) sea

    notificado.

  • 8/18/2019 Java SCJP clase9

    40/40

    Preguntas