SlideShare ist ein Scribd-Unternehmen logo
1 von 22
Downloaden Sie, um offline zu lesen
Java World – Capítulo 7   2

Capítulo 8 – Clases internas                                                                                                                  h
Una clase interna básicamente es lo que el nombre indica, una clase que se encuentra dentro de otra clase. Existen diferentes tipos           t
de ellas, y las maneras de instanciar las mismas también es diferente, de manera que las veremos una a una.                                   t
                                                                                                                                              p
Durante el capítulo veremos 4 conceptos:                                                                                                      :
           Clases internas                                                                                                                   /
                o Clases internas normales                                                                                                    /
                o Clases internas de método                                                                                                   g
                o Clases internas anónimas                                                                                                    u
           Clases estáticas anidadas                                                                                                         s
Algunas reglas sobre las clases internas:                                                                                                     t
                                                                                                                                              a
           Tienen acceso a todos los atributos y métodos de su clase contenedora, por más que los mismos sean private.                       v
           Debe de existir una instancia de la clase contenedora para poder crear una instancia de la clase interna, sin excepción.
                                                                                                                                              o
           Las clases internas siempre mantienen una referencia a la clase contenedora.
                                                                                                                                              a
           Al igual que las clases normales, no es posible definirlas como abstract y final.
                                                                                                                                              l
Clase interna normal                                                                                                                          b
                                                                                                                                              e
  class Externa {                                                                                                                             r
    class Interna {
                                                                                                                                              o
    }
  }                                                                                                                                           l
                                                                                                                                              a
Primer punto a tener en cuenta, es que este código al precompilarlo genera dos clases:                                                        .
                                                                                                                                              b
           Externa.class
                                                                                                                                              l
           Externa$Interna.class
                                                                                                                                              o
                                                                                                                                              g
                         Una clase interna no puede tener métodos estáticos.                                                                  s
                                                                                                                                              p
                                                                                                                                              o
Instanciación                                                                                                                                 t
                                                                                                                                              .
Desde dentro de la clase externa, la clase interna es visible, de manera que lo siguiente es válido:
                                                                                                                                              c
                                                                                                                                              o
  class Externa {                                                                                                                             m
    public void hazAlgo() {
      Interna i = new Interna();
    }

          class Interna {
          }
  }
A su vez, la clase interna tiene conocimiento de la clase externa, pudiendo acceder a sus métodos y atributos como propios.
3    Java World – Capítulo 7

        Instanciación fuera de la clase
h
t       Dado que una clase interna puede acceder a los atribútos y métodos de la clase externa, esto nos dice una cosa: “tiene que haber
t       primero una instancia de la clase externa para que pueda existir una instancia de la clase interna”.
        Bien, según el código anterior, la instanciación de ambas clases desde fuera de la clase sería:
p
:
          Externa externa = new Externa();
/         Externa.Interna interna = externa.new Interna();
/
v
a       Referenciando a la clase externa desde la interna
l       Dado que el modificador this se encuentra reservado para el objeto que llamó el método actual en ejecución, no nos sirve para
o       invocar otra instancia. Para poder referenciar a instancia de la clase externa dentro de la interna la sintaxis sería:
                 [NombreClaseExterna].this
r
c
r         class Externa {
            class Interna {
e
              public void hazAlgo() {
a               Externa externa = Externa.this; //Referencia de la clase contenedora
t               Interna interna = this;         //Referencia de la propia clase interna
              }
i           }
v         }
o
.       Modificadores aplicables
b       Los modificadores de acceso que se pueden aplicar a la clase interna normal son:
l
               final
o              abstract
g              public
s              private
p              protected
o              static (transforma la clase en una clase común. Lo veremos más adelante)
t              strictfp

.       Clase interna de método local
c       Es posible declarar una clase interna dentro de un método.
o
m         class Externa {
            public void hazAlgo() {
              class Interna {
                public void hazOtraCosa() {}
              }
            }
          }



                             El que hayas declarado una clase de método local no significa que hayas creado una instancia de esta clase.




        De manera que si quisieramos crear una instancia de Interna, esto solo podría realizarse dentro del método hazAlgo().
Java World – Capítulo 7   4

Cosas que se pueden y no hacer dentro de una clase interna de método                                                                    h
                                                                                                                                        t
        No se puede acceder a las variables definidas dentro del método, salvo que estas se definan como final.
        Puede acceder a los atributos de la clase externa.
                                                                                                                                        t
              o Solo podrá acceder a atributos estáticos, si es que fue declarada como static (no existe el this).                      p
        La clase puede declararse dentro del método, pero la referencia puede almacenarse en otra referencia, de manrea que            :
         finalizado el método el objeto siga existiendo.                                                                                /
                                                                                                                                        /
Modificadores aplicables
                                                                                                                                        g
Los modificadores de acceso que se pueden aplicar a una clase interna de método local son:                                              u
       abstract                                                                                                                        s
       final                                                                                                                           t
Clases internas anónimas                                                                                                                a
                                                                                                                                        v
Estas conforman las porciones de código más extrañas que podamos encontrar en Java. Veamos un ejemplo primero:
                                                                                                                                        o
                                                                                                                                        a
  class ClaseDos {
    public void hazAlgo() {}                                                                                                            l
  }                                                                                                                                     b
  class Original {                                                                                                                      e
    ClaseDos c = new ClaseDos() {                                                                                                       r
       public void hazAlgo() {                                                                                                          o
         System.out.println("Método pop sobrescrito");
       }                                                                                                                                l
    };                                                                                                                                  a
  }
                                                                                                                                        .
                                                                                                                                        b
                                                                                                                                        l
                     La declaración de una clase anónima debe cerrar la última llave con un ; (punto y coma), salvo que se este
                     definiendo como parámetro de un método.                                                                            o
                                                                                                                                        g
                                                                                                                                        s
El concepto de anónima viene porque se está sobreescribiendo una clase (o interfaz), pero no se está definiendo un nuevo tipo.
                                                                                                                                        p
Conceptos a tener en cuenta de la clase anónima:                                                                                        o
                                                                                                                                        t
       La clase anónima puede extender de una clase normal, abstract o implementar una interface, pero solo puede
                                                                                                                                        .
        extender/implementar de una de las anteriores mencionadas (no puede extender de a e implementar la interfaz b).
       Desde fuera de la clase anónima solo se pueden invocar los métodos definidos en la super clase o interfaz.                      c
       Se pueden crear nuevos métodos, pero estos solo pueden ser invocados desde otro método de la clase anónima.                     o
       También es posible crear una clase anónima como parámetro de una función.                                                       m
5    Java World – Capítulo 7

        Veamos un ejemplo de una clase anónima declarada como parámetro de un método, que a su vez extiende de una clase abstract.
h
t         class Perro {
            public void perseguir(Gato g) {
t             System.out.println("El perro comienza a perseguir al gato");
p             g.huir();
            }
:
          }
/
/         abstract class Gato {
            abstract public void huir();
v         }
a
          class Duenio {
l           public void hazAlgo() {
o             Perro p = new Perro();
r             p.persegir(new Gato() {
                public void huir() {
c                 System.out.println("El gato logró huir exitosamente");
r               }
              });
e           }
a         }
t
i
                            El perro comienza a perseguir al gato
v
                            El gato logró huir exitosamente
o
.
b
        Crear una clase anónima a partir de una interfaz
l
        Una clase anónima puede implementar una interfaz, pero la declaración de la misma no es como se hace normalmente. Veamos un
o
        ejemplo:
g
s         interface Animal {
p           public void emitirSonido();
          }
o
t         class Familia {
            Animal mascota = new Animal() {
.              public void emitirSonido() {
c                System.out.println("wof wof!");
o              }
            };
m           mascota.emitirSonido();
          }




                           wof wof!




        Como podemos apreciar, se utiliza tanto clases como interfaces de la misma manera en cuanto a clases anónimas se refiere.
        new [Class o Interface]() {}
Java World – Capítulo 7   6

Clases estáticas anidadas                                                                                                                 h
Una clase estática anidada es simplemente una clase definida como un atributo estático de la clase padre.                                 t
                                                                                                                                          t
Conceptos que cambian con respecto a las clases internas:                                                                                 p
        No requieren de una clase externa para poder crear una instancia de la interna.                                                  :
        No pueden acceder a atributos y métodos de la clase externa que no estén definidos como static.                                  /
        Se comporta como una clase normal, solo que la ruta de acceso es a través de ClaseExterna.ClaseInterna.                          /
             o Salvo en el caso que estemos en un método de la clase externa, en el cual la clase interna puede ser accedida              g
                 directamente como ClaseInterna.
                                                                                                                                          u
                                                                                                                                          s
 class Persona {
   static class Personita {                                                                                                               t
     public void hazAlgo() {                                                                                                              a
       System.out.println("Personita hace algo");
     }
                                                                                                                                          v
   }                                                                                                                                      o
 }                                                                                                                                        a
 public class General {                                                                                                                   l
                                                                                                                                          b
     static class Cabo {
       public void hazAlgo() {                                                                                                            e
         System.out.println("Cabo hace algo");                                                                                            r
       }
     }
                                                                                                                                          o
     // Tener en cuenta que el método main está definido dentro de General                                                                l
     static public void main(String[] args) {                                                                                             a
       Persona.Personita p = new Persona.Personita();
       Cabo c = new Cabo();                                                                                                               .
       p.hazAlgo(); // Personita hace algo                                                                                                b
       c.hazAlgo(); // Cabo hace algo
     }                                                                                                                                    l
 }                                                                                                                                        o
                                                                                                                                          g
                                                                                                                                          s
                                                                                                                                          p
Capítulo 9 – Hilos de ejecución (Threads)                                                                                                 o
Un hilo de ejecución es un proceso liviano desencadenado por otro proceso, y dependiente de este último. El nuevo hilo tendrá un          t
stack aparte.                                                                                                                             .
En palabras más simples, un hilo de ejecución es un proceso paralelo con respecto al proceso principal, lo que lleva a cabo que en        c
computadoras con más de un nucleo (o emulados), haya varios procesos ejecutando nuestro código al mismo tiempo.                           o
                                                                                                                                          m
Que representa para Java un Thread?

        Una clase java.lang.Thread
        Un hilo de ejecución

Para el examen es necesario conocer cuando una sintaxis está creando código multithread seguro y cuando no.
7    Java World – Capítulo 7

        Creando un thread
h
t       Dentro de la clase java.lang.Thread se encuentran una serie de métodos. Dentro de estos deberás de conocer los siguientes:
t
               start()
p              yield()
:              sleep()
/              run()
/
        Para poder crear un nuevo Thread debes de cumplir el contrato de la interfaz java.lang.Runnable, el cual tiene un solo método:
v
        public void run();
a       Para ello, la clase que utilicemos tiene que implementar dicha interfaz, o extender la clase java.lang.Thread.
l
o       Definiendo un Thread extendiendo Thread
r
c         class MiClaseThread extends Thread {
r           public void run() {
              System.out.println("Oh, JavaWorld esta en un Thread!");
e           }
a         }
t
i
        Definiendo un Thread implementando Runnable
v
o
          class MiClaseRunnable implements Runnable {
.           public void run() {
b             System.out.println("Oh, JavaWorld esta en un Thread!");
            }
l         }
o
g
        Instanciando un Thread
s
p       Si o si es necesaria una instancia de Thread para poder correr un hilo de ejecución.
o       Para eso tenemos dos posibilidades, dependiendo de si extendimos de Thread, o implementamos Runnable.

t       Instanciando un Thread que extiende de Thread
.
c        Thread hilo = new miClaseConThread();
o       Creamos un objeto MiClaseConThread y lo asignamos a una referencia de tipo Thread, dado que extiende de Thread, la relación Is-A
m       Thread es legal.

        Instanciando un Thread que implementa Runnable

          Runnable hiloRunnable = new miClaseConThread();
          Thread hilo = new Thread(hiloRunnable);
          // O la versión abreviada
          Thread hilo = new Thread(new miClaseConThread());
        En este caso, lo que hacemos es primero crear una instancia de nuestra clase y almacenarla en una referencia de tipo Runnable.
        Luego, utilizamos uno de los constructores sobrecargados de Thread, el cual recibe un objeto de tipo Runnable.
Java World – Capítulo 7      8

La clase Thread                                                                                                                                h
Como mencionamos anteriormente, Thread tiene una serie de constructores sobrecargados:                                                         t
                                                                                                                                               t
         Thread()
                                                                                                                                               p
         Thread(Runnable objetivo)
                                                                                                                                               :
         Thread(Runnable objetivo, String nombre)
         Thread(String nombre)
                                                                                                                                               /
                                                                                                                                               /
Si probamos los códigos anteriores en una aplicación en Java, notaríamos que no pasa nada. La cuestión es que el instanciar un                 g
Thread no hace que se lance el hilo de ejecución del mismo, de manera que no se ejecuta. Para poder determinar en que
                                                                                                                                               u
condiciones de ejecución se encuentra el Thread lo podemos clasificar en tres estados:
                                                                                                                                               s
Estado         Descripción                                                                                                                     t
new            Cuando un Thread ha sido instanciado (invocación del new) se encuentra en estado nuevo.                                         a
(nuevo)                                                                                                                                        v
alive          Cuando el hilo de ejecución es lanzado (se crea un nuevo stack para el hilo y se ejecuta el contenido de run() ), se dice       o
(vivo)         que el Thread está vivo.                                                                                                        a
dead           Cuando el hilo de ejecución completa el método run, se dice que el Thread está muerto.                                          l
(muerto)                                                                                                                                       b
Iniciando la ejecución de un Thread                                                                                                            e
Simplemente, para iniciar la ejecución de un nuevo Thread, se utiliza el método start().                                                       r
                                                                                                                                               o
  Runnable hiloRunnable = new miClaseConThread();
  Thread hilo = new Thread(hiloRunnable);                                                                                                      l
  hilo.start();                                                                                                                                a
                                                                                                                                               .
Tambien hay que tener mucho cuidado con la llamada a run(). Cuando invocamos el método start(), este primero crea un nuevo                     b
stack, y luego lanza el método run() como miembro inicial de dicho stack en un hilo de ejecución aparte.
                                                                                                                                               l
                                                                                                                                               o
                      Si se invoca directamente el método run() no generará un error, pero el mismo no se ejecutará en un nuevo                g
                      thread, sino que sería como llamar a un método normal.                                                                   s
                                                                                                                                               p
                                                                                                                                               o
                                                                                                                                               t
                                                                                                                                               .
                                                                                                                                               c
                                                                                                                                               o
                                                                                                                                               m
9    Java World – Capítulo 7

        Ejecutando Threads
h
t       Vamos a lo que nos concierne, corramos algunos hilos:
t         class PruebasRunnable implements Runnable {
p           private int iteraciones = 4;
:
              public void run() {
/               for (int x = 0 ; x < iteraciones; x++ ) {
/                 System.out.println("Ejecutando [" + Thread.currentThread().getName() + "] [" + x
                                      + "]");
v               }
a             }
l
              static public void main(String[] args) {
o               Runnable hilo = new PruebasRunnable();
r
                  Thread hilo1 = new Thread(hilo, "Hilo 1");
c                 Thread hilo2 = new Thread(hilo, "Hilo 2");
r                 Thread hilo3 = new Thread(hilo, "Hilo 3");
e                 hilo1.start();
a                 hilo2.start();
                  hilo3.start();
t
              }
i         }
v
o                          Ejecutando      [Hilo    1]   [0]
.                          Ejecutando      [Hilo    2]   [0]
b                          Ejecutando      [Hilo    3]   [0]
                           Ejecutando      [Hilo    2]   [1]
l                          Ejecutando      [Hilo    1]   [1]
o                          Ejecutando      [Hilo    2]   [2]
g                          Ejecutando      [Hilo    3]   [1]
s                          Ejecutando      [Hilo    2]   [3]
                           Ejecutando      [Hilo    1]   [2]
p
                           Ejecutando      [Hilo    3]   [2]
o                          Ejecutando      [Hilo    1]   [3]
t                          Ejecutando      [Hilo    3]   [3]
.
c
o                            El orden de ejecución de los hilos no puede ser jamás predecido.
m


        Por más que conozcamos el orden en que son inicializados, ni siquiera esto nos asegura de que el orden de ejecución de los mismos
        sea ese.
        El sistema de hilos y tareas es manejado por el Sistema Operativo en conjunto con la JVM, son ellos quienes asignarán el proceso y
        otorgaran los tiempos que el mismo se encuentra en ejecución.
        Otra cuestión a tener en cuenta es que un Thread solo puede ser llamado una única vez en toda su existencia.


                             El llamar al método start() más de una vez desde el mismo Thread generará el lanzamiento de una
                             excepción IllegalThreadStateException.
Java World – Capítulo 7   10

Estados y transiciones de los threads                                                                                                     h
En total podemos contar 5 estados en los cuales puede estar un thread. Veamos un gráfico de esto para entender un poco mejor:             t
                                                                                                                                          t
                             Alive (vivo)                                                                                                 p
                                                           Waiting                                                                        :
                                                          /Blocking                                                                       /
             New                                         (esperando                                          Dead                         /
           (nuevo)                                      /bloqueado)                                        (muerto)                       g
                                                                                                                                          u
                                                                                                                                          s
                                                                                                                                          t
                                    Runnable                                      Running                                                 a
                                   (esperando                                        (en
                                                                                                                                          v
                                    ejecución)                                   ejecución)
                                                                                                                                          o
                                                                                                                                          a
                                                                                                                                          l
                                                                                                                                          b
                                                                                                                                          e
Tabla de estados
Estado                     Descripción                                                                                                    r
New                        Este estado se da cuando se ha invocado al new del Thread, pero aun no se ha llamado al método                 o
(nuevo)                    start().                                                                                                       l
Runnable                   Este estado se da cuando el thread se encuentra listo para ser ejecutado, y está esperando que el              a
(esperando ejecución)      gestionador de eventos de la JVM lo seleccione para comenzar la ejecución.                                     .
Running                    Este estado se da cuando el thread fue seleccionado por el gestionador de eventos y se encuentra               b
(en ejecución)             actualmente en ejecución.
                                                                                                                                          l
Waiting/Block              Este estado se da cuando el thread requiere algún recurso (I/O por ejemplo), de manera que para
(esperando/bloqueado)      no consumir recursos de CPU queda esperando. También puede pasar que se le haya ordenado que
                                                                                                                                          o
                           se durmiera, de manera que despertará cuando acabe el tiempo (si se especificó), o que otro thread             g
                           le envíe una señal para despertarlo.                                                                           s
Dead                       Este estado se da cuando el thread completó la ejecución del método run. Aun sigue siendo un                   p
(muerto)                   objeto, el cual solicito que se liberarn sus recursos.                                                         o
Durmiendo (Sleep)                                                                                                                         t
Sleep es un método estático de la clase Thread. Este solo puede afectar al Thread que actualmente se está ejecutando, de manera           .
que un Thread no puede dormir a otro.                                                                                                     c
Cuando un Thread es enviado a dormir pasa al estado de “Esperando/Bloqueado”.                                                             o
Los métodos sleep son:
                                                                                                                                          m
       sleep()
       sleep(long milisegundos)

El primero envía el thread a “Esperando” hasta que otro thread lo despierte mediante “nofity/notifyAll”.
El segundo lo duerme por un tiempo determinado.

                      Cuando se especifica un tiempo de sleep, este representa el tiempo mínimo que el thread permanecerá
                      dormido, pero no es el tiempo exacto.
11    Java World – Capítulo 7

         Además, este método puede generar una excepción InterruptedException, por lo que hay que llamarlo dentro de un Try-Catch.
h        Hagamos un ejemplo simple:
t
t
           import java.lang.InterruptedException;
p
:          public class PruebasRunnable01 implements Runnable {
/            static public void main(String[] args) {
               (new Thread(new PruebasRunnable01())).start();
/            }
v
                   public void run() {
a                    for (int x = 1 ; x <= 101 ; x ++) {
l                      if (x%10 == 0) {
                         System.out.println("Running " + x);
o
                       }
r                      try {
c                        Thread.sleep(500); // 1 milisegundo * 500 = 1/2 segundo
                       } catch(InterruptedException ex) {}
r                    }
e                  }
           }
a
t
i        Yield() y threads con prioridades
v        Los threads siempre se ejecutan con una prioridad, generalmente, esta se representa con un número del 1 al 10.
o        Algunas JVM´s utilizan una lógica de “tiempo cíclico”, la cual asigna un tiempo determinado a un thread para que se ejecute. Si el
.        thread excede el tiempo, se pausa su ejecución, y se devuelve a la lista de “esperando ejecución”, dando la oportunidad a otro
b        thread para que se ejecute. Otras utilizan una lógica que permiten a un thread ejecutarse hasta la finalización del método run.
l        Las prioridades funcionan de manera que se ordena la lista de “esperando ejecución” de menor a mayor por prioridad, siempre
         pasando a “en ejecución” a los threads de mayor prioridad.
o
g
s                                 La JVM no especifica que las prioridades se sigan al pie de la letra, de manera que solo utilizamos estas para
p                                 optimizar el código, pero no dependan de ellas para determinar la lógica del programa.
o
t
.        Esto nos deja con dos posibles comportamientos:

c                   Se obtiene un thread de la lista de “esperando ejecución” y se lo ejecuta hasta que se complete o se bloque.
o                   Se utilizan tiempos máximos de ejecución, de manera que todos los threads (o la gran mayoría), tengan una oportunidad de
m                    ejecutarse.

         Estableciendo la prioridad de los threads
         El thread recibe una prioridad por defecto, la cual corresponde a la prioridad del thread con que fue creado. Esta comprende un
         rango que va generalmente del 1 al 10, pero no todas las JVM´s contienen este rango.
         Por defecto, los threads main son creados con prioridad 5.
         Existen también algunos identificadores en la clase Thread para indicar las prioridades:

                    Thread.MIN_PRIORITY               1
                    Thread.NORM_PRIORITY              5
                    Thread.MAX_PRIORITY               10

         La prioridad se establece mediante el método setPriority(int prioridad). Este es un método de instancia perteneciente a la clase
         Thread.
Java World – Capítulo 7     12

Ejemplo:
                                                                                                                                           h
  Thread t = new MiThread();                                                                                                               t
  t.setPriority(Thread.MAX_PRIORITY);                                                                                                      t
  t.start();
                                                                                                                                           p
La JVM nunca cambiará la prioridad de un thread.
                                                                                                                                           :
El método yield()
                                                                                                                                           /
Este método lo que hace es enviar una sugerencia a la JVM para que el thread actual pase a la lista de “esperando ejecución”. Pero
                                                                                                                                           /
hay que tener en cuenta que esto es una sugerencia, y puede que nunca se cumpla. También puede que se cumpla, pero al enviar el
thread a la lista de “esperando ejecución”, vuelva a ser elegido el mismo y pase a la lista de “en ejecución”.
                                                                                                                                           g
Mediante el método yield(), el thread nunca pasará al estado de “Esperando”. Este es un método de clase perteneciente a la clase           u
Thread.                                                                                                                                    s
                                                                                                                                           t
El método join()
                                                                                                                                           a
Este método permite unir la ejecución de un thread al final de la otra. Supongamos que tenemos dos threads A y B. A requiere que B
                                                                                                                                           v
se ejecute para poder continuar, de manera que A realiza un join contra B. Cuando B termine su ejecución, recién en ese momento A
                                                                                                                                           o
será candidato a ser elegido de la lista de “esperando ejecución”, pero no antes.
Este es un método de instancia perteneciente a la clase Thread.                                                                            a
                                                                                                                                           l
Sincronización de código                                                                                                                   b
La sincronización es el termino utilizado para que varios elementos que utilizan un recurso compartido no generen inconsistencia de        e
datos.                                                                                                                                     r
En el siguiente ejemplo de código pueden ver un caso en particular con una cuenta bancaria. Ejecutenlo varias veces y verán como a
                                                                                                                                           o
veces el saldo queda en negativo y otras no.
                                                                                                                                           l
Para ver el ejemplo, dirígete al enlace y compila el código.                                                                               a
                                                                                                                                           .
Lo que debemos hacer en orden de preservar la integridad de la cuenta es que el método “efectuarRetiro” se realice de manera               b
atómica (en realidad el término no es del todo correcto, dado que una operación atómica es aquella que solo contiene una                   l
instrucción. En este caso, se utiliza para identificar un conjunto de instrucciones que deben de procesarse como una sola).                o
Para ello podemos utilizar el modificador synchronized. Este lo que hace es asegurarse de que solo un objeto por vez pueda
                                                                                                                                           g
acceder al recurso (en este caso el método), pero no asegura que el objeto ejecute en una pasada todo el código.
Si un objeto ejecuta el código y se interrumpe dentro del mismo, se mantiene una llave, de manera que otro objeto no pueda                 s
acceder hasta que el que estaba bloqueado, vuelva y termine con la ejecución.                                                              p
                                                                                                                                           o
Veamos el mismo ejemplo pero ahora sincronizado. Ejecutenlo las veces que quieran. Verán que el saldo de la cuenta jamás será              t
negativo.                                                                                                                                  .
                                                                                                                                           c
Para ver el ejemplo, dirígete al enlace y compila el código.
                                                                                                                                           o
                                                                                                                                           m
13    Java World – Capítulo 7

         Sincronización y bloqueos
h
t        La sincronización funciona mediante bloqueos. Denominamos bloqueo al método que implementa synchronized, y monitor al
t        objeto que accede al bloqueo.
         Puntos clave sobre synchronized:
p
:              Solo se pueden sincronizar métodos o bloques de código.
/              Cada objeto solo tiene un bloqueo.
/              No es necesario sincronizar todos los métodos de una clase.
v              Solo puede acceder un monitor al bloqueo por vez.
a              Si se utiliza la sincronización en forma incorrecta, se pueden llegar a generar deadlocks (bloqueos de la muerte). Esto
                sucede cuando dos objetos, contienen un bloqueo, y ambos requieren acceder al bloqueo del contrario.
l
               Si un thread pasa a “esperando/bloqueado”, este mantiene todos los bloqueos que tiene (continua siendo monitor).
o
               Un thread puede adquirir más de un bloqueo.
r              Es posible sincronizar un bloque de código en vez de un método completo.
c
r
e          //Método de instancia sincronizado
a          public synchronized hazAlgo() {
             System.out.println("Codigo sincronizado");
t          }
i          //Bloque de código de instancia sincronizado
           public void hazAlgo() {
v            synchronized(this) {
o              System.out.println("Codigo sincronizado");
.            }
           }
b          //Método de clase sincronizado
l          static public synchronized hazAlgo() {
             System.out.println("Static - Codigo sincronizado");
o          }
g          //Bloque de código de clase sincronizado
           static public hazAlgo() {
s            synchronized(MyClase.class) {
p              System.out.println("Static - Codigo sincronizado");
o            }
           }
t
.
c
o
m
Java World – Capítulo 7       14

Que pasa si un thread no obtiene el bloqueo?                                                                                                      h
Si un objeto intenta acceder a por ejemplo un método sincronizado, y este ya está bloqueado, el objeto en cuestión queda en una                   t
lista de espera especial para cuando el bloqueo sea liberado.                                                                                     t
No hay una lógica que indique en que orden se obtiene el próximo objeto que se encuentra en la lista esperando el bloqueo.                        p
Cuadro de cómo afectan los métodos de threads a los bloqueos
                                                                                                                                                  :
Libera el bloqueo                           Mantiene el bloqueo                     Clase que contiene el método
                                                                                                                                                  /
wait()                                        notify()                                    java.lang.Object
                                              join()                                      java.lang.Thread
                                                                                                                                                  /
                                              sleep()                                     java.lang.Thread                                        g
                                              yield()                                     java.lang.Thread                                        u
Cuando es necesario sincronizar?                                                                                                                  s
Generalmente, siempre que utilicemos threads será necesario que hagamos uso de la sincronización, siempre que tanto en métodos                    t
estáticos como no estáticos, haya datos que puedan sufrir modificaciones y que no sean de tipo local, se deberán de marcar como                   a
synchronized.                                                                                                                                     v
Hay un pequeño tema, dijimos que cada clase tiene un bloqueo disponible, pero es uno para la clase y uno para la instancia (static                o
y no static). El problema es que si un método de clase llama a un atributo estático, y el primero está sincronizado, solo se toma un              a
bloqueo, el de la clase. Y si otro objeto llama al método estático, y este llama al atributo de clase, solo se toma el bloqueo estático. Y
                                                                                                                                                  l
con esto ambos objetos pudieron saltear los bloqueos del otro.
De más está decir que esta situación debes evitarla siempre que sea posible de manera que:
                                                                                                                                                  b
                                                                                                                                                  e
        Los atributos estáticos solo se deben invocar desde métodos estáticos sincronizados.                                                     r
        Los atributos de clase solo se deben invocar desde métodos de clase sincronizados.                                                       o
                                                                                                                                                  l
Clases multi-hilo seguro
                                                                                                                                                  a
Cuando una clase contiene métodos synchronized cuidadosamente colocados, se denomina que la clase es multi-hilo seguro
                                                                                                                                                  .
(Thread-Safe). Pero hay un problema, que la clase sea thead-safe no quita que podamos implementarla de manera incorrecta,
produciendo posibles corrupciones de datos.
                                                                                                                                                  b
De manera que cuando utilicemos threads, debemos depender de la clase que llevaría a cabo la operación atómica.                                   l
                                                                                                                                                  o
Bloqueos de la muerte
                                                                                                                                                  g
Esto se produce cuando dos bloqueos esperan que se libere el bloqueo del contrario para poder continuar. Esto generalmente es un                  s
error muy difícil de detectar, además de que cuando trabajamos con threads, el reproducir el error es aun más complicado.
                                                                                                                                                  p
Interacción entre threads                                                                                                                         o
Para comunicarse entre si, se utilizan los método: wait(), notify() y notifyAll().                                                                t
                                                                                                                                                  .
                                                                                                                                                  c
                       wait(), notify(), notifyAll() solo pueden ser invocados desde un contexto sincronizado. Un objeto no puede                 o
                       ionvocar dichos métodos a menos que posea el bloqueo.
                                                                                                                                                  m


Los métodos wait() y notify() pertenecen a la clase Object.
Un objeto puede tener una lista con 0 .. * (0 a muchos) objetos esperando que se les notifique cuando la ejecución de este haya
terminado, o el bloqueo se haya liberado. Veamos un ejemplo:
15    Java World – Capítulo 7


h
t          //Compilación:           javac -g PruebasRunnable04.java
           //Ejecución:             java PruebasRunnable04
t
p          public class PruebasRunnable04 {
             static public void main(String[] args) {
:
               (new PruebasRunnable04(new Object())).pruebaWait();
/            }
/
               private Object bloqueador;
v
a              public PruebasRunnable04(Object bloqueador) {
                 this.bloqueador = bloqueador;
l              }
o
r              public void pruebaWait() {
                 Incrementador incrementador = new Incrementador(bloqueador);
c                (new Thread(incrementador)).start();
r
                   synchronized(bloqueador) {
e                    try {
a                      System.out.println("Esperando a que se complete el incrementador...");
                       bloqueador.wait();
t                    } catch(InterruptedException ex) {}
i                    System.out.println("El total es: " + incrementador.getTotal());
v                  }
               }
o
.          }
           class Incrementador implements Runnable {
b            private int contador = 0;
l            private Object bloqueador;
             public Incrementador(Object bloqueador) {
o              this.bloqueador = bloqueador;
g            }
s
               public int getTotal() {
p                return contador;
o              }
t              public void run() {
.                synchronized(bloqueador) {
                   for(int x = 0 ; x < 100 ; x++) {
c                    contador++;
o                    System.out.print(".");
m                    try {
                       Thread.sleep(100);
                     } catch(InterruptedException ex){}
                   }
                   System.out.println();
                   bloqueador.notify();
                 }
               }
           }


         En el código anterior, no se ejecuta la sentencia que muestra el total hasta que Incrementador no emite el notify indicando que
         puede continuar.
         La importancia del código anterior radica en que para poder llamar al método wait del objeto bloqueador, se debe de poseer el
         bloqueo del mismo.
Java World – Capítulo 7   16

Al igual que sleep(), wait() contiene una sobrecarga: wait(long milisegundos). Esto tiene como propósito poner un límite de tiempo
                                                                                                                                             h
en la espera, ejecutando lo que ocurra primero (ya sea notify() o el tiempo ha transcurrido).
                                                                                                                                             t
                                                                                                                                             t
                      Cuando se ejecuta un notify() no quiere decir que se libere el bloqueo. Esto se realizará una vez que se salga         p
                      del código sincronizado.                                                                                               :
                                                                                                                                             /
                                                                                                                                             /
Utilizando notifyAll() cuando varios threads puedan estar esperando                                                                          g
Si más de un thread se encontraba esperando que se le notifique, al ejecutar notifyAll() todos aquellos que se encuentren en dichas
                                                                                                                                             u
condiciones competirán por parar al estado “en ejecución”.                                                                                   s
                                                                                                                                             t
Utilizando wait() en un bucle
                                                                                                                                             a
Uno de los casos que podemos encontrar y que no hemos planteado aun es el hecho de que el notify() se ejecute antes que el wait().           v
¿Qué pasaría en esta situación?...
                                                                                                                                             o
Simple, si un objeto estuviera esperando un notify() que no volverá a ejecutarse (esto es así por nuestra lógica del programa), el
                                                                                                                                             a
thread estará esperando eternamente, o hasta que se genere una interrupción (InterruptedException).
                                                                                                                                             l
                                                                                                                                             b
Capítulo 10 - Deployment                                                                                                                     e
                                                                                                                                             r
Todo desarrollo en Java requiere que los archivos sean pre-compilados a bytecodes, los cuales son almacenados en archivos .class, o
                                                                                                                                             o
porque no comprimir todos tus .class en un paquete .jar.
Un recordatorio que mencionamos en el primer capítulo. Para poder compilar los archivos .java debes tener instalada alguna                   l
versión de la JDK (Java Development Kit), no basta con tener la JRE (Java Runtime Environment) instalada.                                    a
                                                                                                                                             .
Compilando con con javac
                                                                                                                                             b
Javac es el comando utilizado para poder transformar nuestros .java a .class (bytecodes). La sintaxis de este es:                            l
javac [opciones] [archivos de código fuente]
                                                                                                                                             o
Los elementos entre [] significan opcional.
                                                                                                                                             g
Múltiples opciones y/o archivos de código fuente deben separarse con caracteres de espacio.
                                                                                                                                             s
Opcion –d                                                                                                                                    p
Por defecto, cuando compilemos nuestros archivos en Java, el directorio destino por defecto será exactamente el mismo que el de              o
los códigos fuente. Para poder modificar esto existe el comando –d.                                                                          t
                                                                                                                                             .
                                                                                                                                             c
                      El directorio que especifiques mediante –d debe existir, de lo contrario generarás un error de compilación.            o
                                                                                                                                             m
17    Java World – Capítulo 7

         Supongamos la siguiente estructura.
h
t
               Directorio Raiz
t
p
:                                source
/
                                            com
/
v                                                       blogspot
a                                                                     gustavoalberola
l
o                                                                                         PruebaJavaWorld.java

r                                classes
c
r        Dentro de source van nuestro .java y dentro de classes nuestros .class.
         Si quisiéramos compilar el código anterior (tengan en cuenta que según la estructura anterior, PruebaJavaWorld.java esta dentro de
e
         los package com, blogspot y gustavoalberola) deberíamos utilizar la sintaxis:
a
t                Parados sobre el directorio “source”
i                javac –d ../classes com/blogspot/gustavoalberola/PruebaJavaWorld.java
v
o        Esto lo que hará es crear dentro de classes la misma jerarquía de directorios, con el .class compilado a bytecode.
.        Ejecutando aplicaciones con java
b
         Una vez que tenemos nuestros .class lo que necsitamos es ejecutar el programa, para ello utilizamos el comando java. Su sintaxis es:
l                java [opciones] clase [argumentos]
o        Por defecto, el comando java interpreta que lo que quieres ejecutar es un .class, de manera que no es necesario especificar la
g        extensión (es más, si la especificas, no podrás ejecutar tu programa).
s        Utilizandos las propiedades de sistema
p
         Dentro de java tenemos una clase denominada java.util.Properties. Esta es utilizada para obtener las propiedades por defecto del
o
         sistema operativo, el compilador de java, la jvm, y también para guardar nuestras propias propiedades.
t        Veamos un ejemplo simple:
.
c          import java.util.Properties;
o
           public class Pruebas_01 {
m            static public void main(String[] args) {
               Properties propiedades = System.getProperties();
               propiedades.setProperty("MiPropiedad", "MiValor");
               propiedades.list(System.out);
             }
           }
Java World – Capítulo 7   18

Ejecutando el programa con:
                                                                                                                                      h
          java -DMyOtraPripiedad="Aun no decido que valor poner" Pruebas_01
                                                                                                                                      t
El resultado es algo asi:
                                                                                                                                      t
                                                                                                                                      p
                   java.runtime.name=Java(TM) SE Runtime Environment
                   sun.boot.library.path=C:Program FilesJavajre6bin                                                               :
                   java.vm.version=14.3-b01                                                                                           /
                   java.vm.vendor=Sun Microsystems Inc.                                                                               /
                   java.vendor.url=http://java.sun.com/
                                                                                                                                      g
                   ...
                   java.runtime.version=1.6.0_17-b04                                                                                  u
                   ...                                                                                                                s
                   java.specification.version=1.6                                                                                     t
                   user.name=gustavo                                                                                                  a
                   java.class.path=.
                   MyOtraPripiedad=Aun no decido que valor poner
                                                                                                                                      v
                   ...                                                                                                                o
                   MiPropiedad=MiValor                                                                                                a
                                                                                                                                      l
                                                                                                                                      b
Vemos como tanto la variable que declaramos en código, como aquella que introducimos mediante –D existen en el listado de
propiedades.                                                                                                                          e
Manejando argumentos de la línea de comandos                                                                                          r
                                                                                                                                      o
Todos losargumentos que se escriban en el momento de ejecución entran en el array de Strings del método main, empezando por el
índice 0 para el primer argumento, y así sucesivamente.                                                                               l
                                                                                                                                      a
                                                                                                                                      .
  public class Pruebas_02 {
    static public void main(String[] args) {                                                                                          b
      int x = 0;                                                                                                                      l
      for(String s : args) {
        System.out.println("Argumento [" + x++ + "] = " + s);                                                                         o
      }                                                                                                                               g
    }
  }                                                                                                                                   s
                                                                                                                                      p
Ejecutando el comando                                                                                                                 o
        java Pruebas_02 soy1 "Y yo que?" 1234568                                                                                      t
                                                                                                                                      .
                   Argumento [0] = soy1                                                                                               c
                   Argumento [1] = Y yo que?                                                                                          o
                   Argumento [2] = 1234568
                                                                                                                                      m
19    Java World – Capítulo 7

         Buscando otras clases
h
t        Cuando compilamos o ejecutamos una aplicación, esta requiere de otras clases para funcionar. Supongamos que estamos en la
t        sección de I/O, y necesitamos la clase File, esta tendría que buscarse en java.io.File. Para ello, java realiza las siguientes acciones:

p                Tanto java como javac buscan otras clases de la misma manera
:                Se procede a buscar una a una las clases necesarias
/                      o Se busca dentro de las clases que vienen estandar con J2SE
/                      o Se busca dentro de los classpath declarados
v                La búsqueda se detiene en la primer coincidencia.
a                El classpath puede ser declarado de dos maneras:
                       o Como variable del sistema operativo
l
                       o Como argumento en la línea de comandos (si se especifica, sobrescribe al classpath de sistema, solo en dicha
o                          invocación).
r
c        Declarando y utilizando classpaths
r        El classpath es una dirección a nivel de directorio en donde se buscaran las clases necesarias para compilar/ejecutar el programa.
e        El classpath a su vez puede estar conformado por varios classpath concatenados mediante un caracter parser que hace de
a        separador.
t        Hay que tener en cuenta que una estructura de directorio se especifica diferente según el S.O. que estemos utilizando:

i                Unix: se utiliza como directorio el / y como separador el :
v                Windows: se utiliza como directorio el  y como separador el ;.
o        Un ejemplo de classpath válido para windows sería:
.               .classes;c:misProyectosclasses;c:;
b
l        Muchas veces cuando ejecutamos un programa podemos toparnos con una excepción ClassNotFoundException. Esto indica que
         la JVM no pudo localizar alguna clase que nuestro programa requiere.
o
         Los classpaths se recorren de izquierda a derecha.
g
s
                                Cuando se utiliza el comando java, este no busca en el directorio donde esta parado las clases, solo en el
p
                                directorio de la JRE. Para que haga lo primero, es necesario especificarlo mediante la opción –classpath o –
o                               cp.
t
.
c        Package y búsqueda
o        Existen dos maneras de referenciar clases desde nuestro código que se encuentran en otro package, mediante imports, o la
m        llamda con el nombre atómico de la clase (el package.classNombre).


           package com.blogspot.gustavoalberola;
           public class JavaWorld {}
Java World – Capítulo 7   20

Dicha clase será almacenada en com/blogspot/gustavoalberola/JavaWorld.java.
                                                                                                                                        h
Para referenciarlo desde otro package podemos utiliza cualquiera de las dos sentencias a continuación:
                                                                                                                                        t
Modo de referencia atómico                                                                                                              t
                                                                                                                                        p
                                                                                                                                        :
  //otro package
  public class OtraClase {                                                                                                              /
    static public void main(String[] args) {                                                                                            /
      com.blogspot.gustavoalberola.JavaWorld javaWorld;
      javaWorld = new com.blogspot.gustavoalberola.JavaWorld();
                                                                                                                                        g
    }                                                                                                                                   u
  }                                                                                                                                     s
                                                                                                                                        t
Modo de referencia mediante imports                                                                                                     a
                                                                                                                                        v
                                                                                                                                        o
  //otro package
  //Tambien podemos utilizar el * en vez de JavaWorld (importa todas las clases del                                                     a
  package)                                                                                                                              l
  import com.blogspot.gustavoalberola.JavaWorld;
                                                                                                                                        b
  public class OtraClase {                                                                                                              e
    static public void main(String[] args) {                                                                                            r
      JavaWorld javaWorld;
      javaWorld = new JavaWorld();                                                                                                      o
    }                                                                                                                                   l
  }
                                                                                                                                        a
                                                                                                                                        .
Paths relativos y absolutos                                                                                                             b
                                                                                                                                        l
La diferencia entre un path relativo y absoluto es:
                                                                                                                                        o
        El path relativo depende de donde se encuentra el directorio actual. Ejemplo: ../ vuelve un directorio hacia arriba.           g
        El path absoluto siempre referencia al mismo lugar sin importar donde se encuentre el directorio actual. Ejemplo:              s
         c:Jre_6_0_17.
                                                                                                                                        p
Archivos JAR                                                                                                                            o
                                                                                                                                        t
Teniendo nuestra aplicación terminada, es probable que quieras comenzar a distribuirla. Puedes tener todos los .class en sus
                                                                                                                                        .
respectivos directorios y distribuirlos solo de esa manera, o puedes generar unn archivo jar que contenga todos los .class.
Algunas reglas con respecto a los .jar                                                                                                  c
                                                                                                                                        o
        Automáticamente genera un directorio META-INF.                                                                                 m
        Automáticamente genera un archivo MANIFEST.MF dentro del directorio anterior.
        Jamás introducirá ninguna de tus clases dentro del directorio META-INF.
        Se copia la estructura del directorio y subdirectorios tal cual estaba en el file system.
        Los comandos java y javac utilizan el .jar con una estructura de directorio normal.


                       Cuando queremos compilar o ejecutar una clase que requiere de otra que se encuentra en un .jar, es
                       necesario especificar en el classpath el directorio junto con el nombre y extensión del .jar.
                       Ejemplo: java -cp=libs/JavaWorld.jar HolaJavaWorld
21    Java World – Capítulo 7


h
t        Utilizando …/jre/lib/ext
t        Cuando instanalamos la JRE, dentro de uno de sus directorios
p        encontramos jre/lib/ext. Dentro se encuentran todas las clases que java
:        utiliza. Si pusiéramos cualquiera de nuestras clases aquí dentro, no
/        necesitaríamos especificar un classpath para referenciarlas.
/        Esto es una práctica poco común, y solo se aconseja para casos personales,
v        pero no como método de distribución de un programa.
         También es importante saber que es muy común encontrar variables
a
         definidas para abreviar un directorio, como por ejemplo JAVA_HOME. Si
l        ves en el examen esto, interpretalo como el directorio de las librerías de
o        java.
r
c
         Utilizando import estáticos                                                   Fin del camino
r        El import estático se utiliza para no tener que escribir el nombre completo   Con esta última entrega concluimos la
         de la constante, método o atributo estático. Ejemplo:
e                                                                                      saga de Java World SCJP. Ha sido un
a                                                                                      camino largo y les agradecemos a todos
t          import static System.out;                                                   aquellos que nos estuvieron siguiendo
i          public class HolaMundo {                                                    todo este tiempo, a aquellos que
v            static public void main(String[] args) {                                  realizaron comentarios y correcciones
               out.println("Hola mundo");
o            }                                                                         sobre los capítulos previos, y a la
.          }                                                                           comunidad en general.
b
l        Muchos aseguran que esto ahorra un par de tecleados a cambio de perder
                                                                                       Nos quedan un par de cositas para subir
o        en la redibilidad del código.
                                                                                       además de la compilación final de todos
g
                                                                                       los capítulos para que les sea más fácil
s                             La llamada debe ser import static, y solo en             descargarlos.
p                             ese orden.
o
                                                                                       Esperamos que el material les sea de
t
.                                                                                      ayuda y cualquier duda o comentario
c                                                                                      que tengan no duden en publicar sus
o                                                                                      comentarios en el blog.
m
                                                                                       Gracias a todos!
Capitulo 8 9-10

Weitere ähnliche Inhalte

Empfohlen

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by HubspotMarius Sescu
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTExpeed Software
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsPixeldarts
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthThinkNow
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfmarketingartwork
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024Neil Kimberley
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)contently
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024Albert Qian
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsKurio // The Social Media Age(ncy)
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Search Engine Journal
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summarySpeakerHub
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next Tessa Mero
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentLily Ray
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best PracticesVit Horky
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project managementMindGenius
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...RachelPearson36
 

Empfohlen (20)

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 

Capitulo 8 9-10

  • 1.
  • 2. Java World – Capítulo 7 2 Capítulo 8 – Clases internas h Una clase interna básicamente es lo que el nombre indica, una clase que se encuentra dentro de otra clase. Existen diferentes tipos t de ellas, y las maneras de instanciar las mismas también es diferente, de manera que las veremos una a una. t p Durante el capítulo veremos 4 conceptos: :  Clases internas / o Clases internas normales / o Clases internas de método g o Clases internas anónimas u  Clases estáticas anidadas s Algunas reglas sobre las clases internas: t a  Tienen acceso a todos los atributos y métodos de su clase contenedora, por más que los mismos sean private. v  Debe de existir una instancia de la clase contenedora para poder crear una instancia de la clase interna, sin excepción. o  Las clases internas siempre mantienen una referencia a la clase contenedora. a  Al igual que las clases normales, no es posible definirlas como abstract y final. l Clase interna normal b e class Externa { r class Interna { o } } l a Primer punto a tener en cuenta, es que este código al precompilarlo genera dos clases: . b  Externa.class l  Externa$Interna.class o g Una clase interna no puede tener métodos estáticos. s p o Instanciación t . Desde dentro de la clase externa, la clase interna es visible, de manera que lo siguiente es válido: c o class Externa { m public void hazAlgo() { Interna i = new Interna(); } class Interna { } } A su vez, la clase interna tiene conocimiento de la clase externa, pudiendo acceder a sus métodos y atributos como propios.
  • 3. 3 Java World – Capítulo 7 Instanciación fuera de la clase h t Dado que una clase interna puede acceder a los atribútos y métodos de la clase externa, esto nos dice una cosa: “tiene que haber t primero una instancia de la clase externa para que pueda existir una instancia de la clase interna”. Bien, según el código anterior, la instanciación de ambas clases desde fuera de la clase sería: p : Externa externa = new Externa(); / Externa.Interna interna = externa.new Interna(); / v a Referenciando a la clase externa desde la interna l Dado que el modificador this se encuentra reservado para el objeto que llamó el método actual en ejecución, no nos sirve para o invocar otra instancia. Para poder referenciar a instancia de la clase externa dentro de la interna la sintaxis sería: [NombreClaseExterna].this r c r class Externa { class Interna { e public void hazAlgo() { a Externa externa = Externa.this; //Referencia de la clase contenedora t Interna interna = this; //Referencia de la propia clase interna } i } v } o . Modificadores aplicables b Los modificadores de acceso que se pueden aplicar a la clase interna normal son: l  final o  abstract g  public s  private p  protected o  static (transforma la clase en una clase común. Lo veremos más adelante) t  strictfp . Clase interna de método local c Es posible declarar una clase interna dentro de un método. o m class Externa { public void hazAlgo() { class Interna { public void hazOtraCosa() {} } } } El que hayas declarado una clase de método local no significa que hayas creado una instancia de esta clase. De manera que si quisieramos crear una instancia de Interna, esto solo podría realizarse dentro del método hazAlgo().
  • 4. Java World – Capítulo 7 4 Cosas que se pueden y no hacer dentro de una clase interna de método h t  No se puede acceder a las variables definidas dentro del método, salvo que estas se definan como final.  Puede acceder a los atributos de la clase externa. t o Solo podrá acceder a atributos estáticos, si es que fue declarada como static (no existe el this). p  La clase puede declararse dentro del método, pero la referencia puede almacenarse en otra referencia, de manrea que : finalizado el método el objeto siga existiendo. / / Modificadores aplicables g Los modificadores de acceso que se pueden aplicar a una clase interna de método local son: u  abstract s  final t Clases internas anónimas a v Estas conforman las porciones de código más extrañas que podamos encontrar en Java. Veamos un ejemplo primero: o a class ClaseDos { public void hazAlgo() {} l } b class Original { e ClaseDos c = new ClaseDos() { r public void hazAlgo() { o System.out.println("Método pop sobrescrito"); } l }; a } . b l La declaración de una clase anónima debe cerrar la última llave con un ; (punto y coma), salvo que se este definiendo como parámetro de un método. o g s El concepto de anónima viene porque se está sobreescribiendo una clase (o interfaz), pero no se está definiendo un nuevo tipo. p Conceptos a tener en cuenta de la clase anónima: o t  La clase anónima puede extender de una clase normal, abstract o implementar una interface, pero solo puede . extender/implementar de una de las anteriores mencionadas (no puede extender de a e implementar la interfaz b).  Desde fuera de la clase anónima solo se pueden invocar los métodos definidos en la super clase o interfaz. c  Se pueden crear nuevos métodos, pero estos solo pueden ser invocados desde otro método de la clase anónima. o  También es posible crear una clase anónima como parámetro de una función. m
  • 5. 5 Java World – Capítulo 7 Veamos un ejemplo de una clase anónima declarada como parámetro de un método, que a su vez extiende de una clase abstract. h t class Perro { public void perseguir(Gato g) { t System.out.println("El perro comienza a perseguir al gato"); p g.huir(); } : } / / abstract class Gato { abstract public void huir(); v } a class Duenio { l public void hazAlgo() { o Perro p = new Perro(); r p.persegir(new Gato() { public void huir() { c System.out.println("El gato logró huir exitosamente"); r } }); e } a } t i El perro comienza a perseguir al gato v El gato logró huir exitosamente o . b Crear una clase anónima a partir de una interfaz l Una clase anónima puede implementar una interfaz, pero la declaración de la misma no es como se hace normalmente. Veamos un o ejemplo: g s interface Animal { p public void emitirSonido(); } o t class Familia { Animal mascota = new Animal() { . public void emitirSonido() { c System.out.println("wof wof!"); o } }; m mascota.emitirSonido(); } wof wof! Como podemos apreciar, se utiliza tanto clases como interfaces de la misma manera en cuanto a clases anónimas se refiere. new [Class o Interface]() {}
  • 6. Java World – Capítulo 7 6 Clases estáticas anidadas h Una clase estática anidada es simplemente una clase definida como un atributo estático de la clase padre. t t Conceptos que cambian con respecto a las clases internas: p  No requieren de una clase externa para poder crear una instancia de la interna. :  No pueden acceder a atributos y métodos de la clase externa que no estén definidos como static. /  Se comporta como una clase normal, solo que la ruta de acceso es a través de ClaseExterna.ClaseInterna. / o Salvo en el caso que estemos en un método de la clase externa, en el cual la clase interna puede ser accedida g directamente como ClaseInterna. u s class Persona { static class Personita { t public void hazAlgo() { a System.out.println("Personita hace algo"); } v } o } a public class General { l b static class Cabo { public void hazAlgo() { e System.out.println("Cabo hace algo"); r } } o // Tener en cuenta que el método main está definido dentro de General l static public void main(String[] args) { a Persona.Personita p = new Persona.Personita(); Cabo c = new Cabo(); . p.hazAlgo(); // Personita hace algo b c.hazAlgo(); // Cabo hace algo } l } o g s p Capítulo 9 – Hilos de ejecución (Threads) o Un hilo de ejecución es un proceso liviano desencadenado por otro proceso, y dependiente de este último. El nuevo hilo tendrá un t stack aparte. . En palabras más simples, un hilo de ejecución es un proceso paralelo con respecto al proceso principal, lo que lleva a cabo que en c computadoras con más de un nucleo (o emulados), haya varios procesos ejecutando nuestro código al mismo tiempo. o m Que representa para Java un Thread?  Una clase java.lang.Thread  Un hilo de ejecución Para el examen es necesario conocer cuando una sintaxis está creando código multithread seguro y cuando no.
  • 7. 7 Java World – Capítulo 7 Creando un thread h t Dentro de la clase java.lang.Thread se encuentran una serie de métodos. Dentro de estos deberás de conocer los siguientes: t  start() p  yield() :  sleep() /  run() / Para poder crear un nuevo Thread debes de cumplir el contrato de la interfaz java.lang.Runnable, el cual tiene un solo método: v public void run(); a Para ello, la clase que utilicemos tiene que implementar dicha interfaz, o extender la clase java.lang.Thread. l o Definiendo un Thread extendiendo Thread r c class MiClaseThread extends Thread { r public void run() { System.out.println("Oh, JavaWorld esta en un Thread!"); e } a } t i Definiendo un Thread implementando Runnable v o class MiClaseRunnable implements Runnable { . public void run() { b System.out.println("Oh, JavaWorld esta en un Thread!"); } l } o g Instanciando un Thread s p Si o si es necesaria una instancia de Thread para poder correr un hilo de ejecución. o Para eso tenemos dos posibilidades, dependiendo de si extendimos de Thread, o implementamos Runnable. t Instanciando un Thread que extiende de Thread . c Thread hilo = new miClaseConThread(); o Creamos un objeto MiClaseConThread y lo asignamos a una referencia de tipo Thread, dado que extiende de Thread, la relación Is-A m Thread es legal. Instanciando un Thread que implementa Runnable Runnable hiloRunnable = new miClaseConThread(); Thread hilo = new Thread(hiloRunnable); // O la versión abreviada Thread hilo = new Thread(new miClaseConThread()); En este caso, lo que hacemos es primero crear una instancia de nuestra clase y almacenarla en una referencia de tipo Runnable. Luego, utilizamos uno de los constructores sobrecargados de Thread, el cual recibe un objeto de tipo Runnable.
  • 8. Java World – Capítulo 7 8 La clase Thread h Como mencionamos anteriormente, Thread tiene una serie de constructores sobrecargados: t t  Thread() p  Thread(Runnable objetivo) :  Thread(Runnable objetivo, String nombre)  Thread(String nombre) / / Si probamos los códigos anteriores en una aplicación en Java, notaríamos que no pasa nada. La cuestión es que el instanciar un g Thread no hace que se lance el hilo de ejecución del mismo, de manera que no se ejecuta. Para poder determinar en que u condiciones de ejecución se encuentra el Thread lo podemos clasificar en tres estados: s Estado Descripción t new Cuando un Thread ha sido instanciado (invocación del new) se encuentra en estado nuevo. a (nuevo) v alive Cuando el hilo de ejecución es lanzado (se crea un nuevo stack para el hilo y se ejecuta el contenido de run() ), se dice o (vivo) que el Thread está vivo. a dead Cuando el hilo de ejecución completa el método run, se dice que el Thread está muerto. l (muerto) b Iniciando la ejecución de un Thread e Simplemente, para iniciar la ejecución de un nuevo Thread, se utiliza el método start(). r o Runnable hiloRunnable = new miClaseConThread(); Thread hilo = new Thread(hiloRunnable); l hilo.start(); a . Tambien hay que tener mucho cuidado con la llamada a run(). Cuando invocamos el método start(), este primero crea un nuevo b stack, y luego lanza el método run() como miembro inicial de dicho stack en un hilo de ejecución aparte. l o Si se invoca directamente el método run() no generará un error, pero el mismo no se ejecutará en un nuevo g thread, sino que sería como llamar a un método normal. s p o t . c o m
  • 9. 9 Java World – Capítulo 7 Ejecutando Threads h t Vamos a lo que nos concierne, corramos algunos hilos: t class PruebasRunnable implements Runnable { p private int iteraciones = 4; : public void run() { / for (int x = 0 ; x < iteraciones; x++ ) { / System.out.println("Ejecutando [" + Thread.currentThread().getName() + "] [" + x + "]"); v } a } l static public void main(String[] args) { o Runnable hilo = new PruebasRunnable(); r Thread hilo1 = new Thread(hilo, "Hilo 1"); c Thread hilo2 = new Thread(hilo, "Hilo 2"); r Thread hilo3 = new Thread(hilo, "Hilo 3"); e hilo1.start(); a hilo2.start(); hilo3.start(); t } i } v o Ejecutando [Hilo 1] [0] . Ejecutando [Hilo 2] [0] b Ejecutando [Hilo 3] [0] Ejecutando [Hilo 2] [1] l Ejecutando [Hilo 1] [1] o Ejecutando [Hilo 2] [2] g Ejecutando [Hilo 3] [1] s Ejecutando [Hilo 2] [3] Ejecutando [Hilo 1] [2] p Ejecutando [Hilo 3] [2] o Ejecutando [Hilo 1] [3] t Ejecutando [Hilo 3] [3] . c o El orden de ejecución de los hilos no puede ser jamás predecido. m Por más que conozcamos el orden en que son inicializados, ni siquiera esto nos asegura de que el orden de ejecución de los mismos sea ese. El sistema de hilos y tareas es manejado por el Sistema Operativo en conjunto con la JVM, son ellos quienes asignarán el proceso y otorgaran los tiempos que el mismo se encuentra en ejecución. Otra cuestión a tener en cuenta es que un Thread solo puede ser llamado una única vez en toda su existencia. El llamar al método start() más de una vez desde el mismo Thread generará el lanzamiento de una excepción IllegalThreadStateException.
  • 10. Java World – Capítulo 7 10 Estados y transiciones de los threads h En total podemos contar 5 estados en los cuales puede estar un thread. Veamos un gráfico de esto para entender un poco mejor: t t Alive (vivo) p Waiting : /Blocking / New (esperando Dead / (nuevo) /bloqueado) (muerto) g u s t Runnable Running a (esperando (en v ejecución) ejecución) o a l b e Tabla de estados Estado Descripción r New Este estado se da cuando se ha invocado al new del Thread, pero aun no se ha llamado al método o (nuevo) start(). l Runnable Este estado se da cuando el thread se encuentra listo para ser ejecutado, y está esperando que el a (esperando ejecución) gestionador de eventos de la JVM lo seleccione para comenzar la ejecución. . Running Este estado se da cuando el thread fue seleccionado por el gestionador de eventos y se encuentra b (en ejecución) actualmente en ejecución. l Waiting/Block Este estado se da cuando el thread requiere algún recurso (I/O por ejemplo), de manera que para (esperando/bloqueado) no consumir recursos de CPU queda esperando. También puede pasar que se le haya ordenado que o se durmiera, de manera que despertará cuando acabe el tiempo (si se especificó), o que otro thread g le envíe una señal para despertarlo. s Dead Este estado se da cuando el thread completó la ejecución del método run. Aun sigue siendo un p (muerto) objeto, el cual solicito que se liberarn sus recursos. o Durmiendo (Sleep) t Sleep es un método estático de la clase Thread. Este solo puede afectar al Thread que actualmente se está ejecutando, de manera . que un Thread no puede dormir a otro. c Cuando un Thread es enviado a dormir pasa al estado de “Esperando/Bloqueado”. o Los métodos sleep son: m  sleep()  sleep(long milisegundos) El primero envía el thread a “Esperando” hasta que otro thread lo despierte mediante “nofity/notifyAll”. El segundo lo duerme por un tiempo determinado. Cuando se especifica un tiempo de sleep, este representa el tiempo mínimo que el thread permanecerá dormido, pero no es el tiempo exacto.
  • 11. 11 Java World – Capítulo 7 Además, este método puede generar una excepción InterruptedException, por lo que hay que llamarlo dentro de un Try-Catch. h Hagamos un ejemplo simple: t t import java.lang.InterruptedException; p : public class PruebasRunnable01 implements Runnable { / static public void main(String[] args) { (new Thread(new PruebasRunnable01())).start(); / } v public void run() { a for (int x = 1 ; x <= 101 ; x ++) { l if (x%10 == 0) { System.out.println("Running " + x); o } r try { c Thread.sleep(500); // 1 milisegundo * 500 = 1/2 segundo } catch(InterruptedException ex) {} r } e } } a t i Yield() y threads con prioridades v Los threads siempre se ejecutan con una prioridad, generalmente, esta se representa con un número del 1 al 10. o Algunas JVM´s utilizan una lógica de “tiempo cíclico”, la cual asigna un tiempo determinado a un thread para que se ejecute. Si el . thread excede el tiempo, se pausa su ejecución, y se devuelve a la lista de “esperando ejecución”, dando la oportunidad a otro b thread para que se ejecute. Otras utilizan una lógica que permiten a un thread ejecutarse hasta la finalización del método run. l Las prioridades funcionan de manera que se ordena la lista de “esperando ejecución” de menor a mayor por prioridad, siempre pasando a “en ejecución” a los threads de mayor prioridad. o g s La JVM no especifica que las prioridades se sigan al pie de la letra, de manera que solo utilizamos estas para p optimizar el código, pero no dependan de ellas para determinar la lógica del programa. o t . Esto nos deja con dos posibles comportamientos: c  Se obtiene un thread de la lista de “esperando ejecución” y se lo ejecuta hasta que se complete o se bloque. o  Se utilizan tiempos máximos de ejecución, de manera que todos los threads (o la gran mayoría), tengan una oportunidad de m ejecutarse. Estableciendo la prioridad de los threads El thread recibe una prioridad por defecto, la cual corresponde a la prioridad del thread con que fue creado. Esta comprende un rango que va generalmente del 1 al 10, pero no todas las JVM´s contienen este rango. Por defecto, los threads main son creados con prioridad 5. Existen también algunos identificadores en la clase Thread para indicar las prioridades:  Thread.MIN_PRIORITY 1  Thread.NORM_PRIORITY 5  Thread.MAX_PRIORITY 10 La prioridad se establece mediante el método setPriority(int prioridad). Este es un método de instancia perteneciente a la clase Thread.
  • 12. Java World – Capítulo 7 12 Ejemplo: h Thread t = new MiThread(); t t.setPriority(Thread.MAX_PRIORITY); t t.start(); p La JVM nunca cambiará la prioridad de un thread. : El método yield() / Este método lo que hace es enviar una sugerencia a la JVM para que el thread actual pase a la lista de “esperando ejecución”. Pero / hay que tener en cuenta que esto es una sugerencia, y puede que nunca se cumpla. También puede que se cumpla, pero al enviar el thread a la lista de “esperando ejecución”, vuelva a ser elegido el mismo y pase a la lista de “en ejecución”. g Mediante el método yield(), el thread nunca pasará al estado de “Esperando”. Este es un método de clase perteneciente a la clase u Thread. s t El método join() a Este método permite unir la ejecución de un thread al final de la otra. Supongamos que tenemos dos threads A y B. A requiere que B v se ejecute para poder continuar, de manera que A realiza un join contra B. Cuando B termine su ejecución, recién en ese momento A o será candidato a ser elegido de la lista de “esperando ejecución”, pero no antes. Este es un método de instancia perteneciente a la clase Thread. a l Sincronización de código b La sincronización es el termino utilizado para que varios elementos que utilizan un recurso compartido no generen inconsistencia de e datos. r En el siguiente ejemplo de código pueden ver un caso en particular con una cuenta bancaria. Ejecutenlo varias veces y verán como a o veces el saldo queda en negativo y otras no. l Para ver el ejemplo, dirígete al enlace y compila el código. a . Lo que debemos hacer en orden de preservar la integridad de la cuenta es que el método “efectuarRetiro” se realice de manera b atómica (en realidad el término no es del todo correcto, dado que una operación atómica es aquella que solo contiene una l instrucción. En este caso, se utiliza para identificar un conjunto de instrucciones que deben de procesarse como una sola). o Para ello podemos utilizar el modificador synchronized. Este lo que hace es asegurarse de que solo un objeto por vez pueda g acceder al recurso (en este caso el método), pero no asegura que el objeto ejecute en una pasada todo el código. Si un objeto ejecuta el código y se interrumpe dentro del mismo, se mantiene una llave, de manera que otro objeto no pueda s acceder hasta que el que estaba bloqueado, vuelva y termine con la ejecución. p o Veamos el mismo ejemplo pero ahora sincronizado. Ejecutenlo las veces que quieran. Verán que el saldo de la cuenta jamás será t negativo. . c Para ver el ejemplo, dirígete al enlace y compila el código. o m
  • 13. 13 Java World – Capítulo 7 Sincronización y bloqueos h t La sincronización funciona mediante bloqueos. Denominamos bloqueo al método que implementa synchronized, y monitor al t objeto que accede al bloqueo. Puntos clave sobre synchronized: p :  Solo se pueden sincronizar métodos o bloques de código. /  Cada objeto solo tiene un bloqueo. /  No es necesario sincronizar todos los métodos de una clase. v  Solo puede acceder un monitor al bloqueo por vez. a  Si se utiliza la sincronización en forma incorrecta, se pueden llegar a generar deadlocks (bloqueos de la muerte). Esto sucede cuando dos objetos, contienen un bloqueo, y ambos requieren acceder al bloqueo del contrario. l  Si un thread pasa a “esperando/bloqueado”, este mantiene todos los bloqueos que tiene (continua siendo monitor). o  Un thread puede adquirir más de un bloqueo. r  Es posible sincronizar un bloque de código en vez de un método completo. c r e //Método de instancia sincronizado a public synchronized hazAlgo() { System.out.println("Codigo sincronizado"); t } i //Bloque de código de instancia sincronizado public void hazAlgo() { v synchronized(this) { o System.out.println("Codigo sincronizado"); . } } b //Método de clase sincronizado l static public synchronized hazAlgo() { System.out.println("Static - Codigo sincronizado"); o } g //Bloque de código de clase sincronizado static public hazAlgo() { s synchronized(MyClase.class) { p System.out.println("Static - Codigo sincronizado"); o } } t . c o m
  • 14. Java World – Capítulo 7 14 Que pasa si un thread no obtiene el bloqueo? h Si un objeto intenta acceder a por ejemplo un método sincronizado, y este ya está bloqueado, el objeto en cuestión queda en una t lista de espera especial para cuando el bloqueo sea liberado. t No hay una lógica que indique en que orden se obtiene el próximo objeto que se encuentra en la lista esperando el bloqueo. p Cuadro de cómo afectan los métodos de threads a los bloqueos : Libera el bloqueo Mantiene el bloqueo Clase que contiene el método / wait() notify() java.lang.Object join() java.lang.Thread / sleep() java.lang.Thread g yield() java.lang.Thread u Cuando es necesario sincronizar? s Generalmente, siempre que utilicemos threads será necesario que hagamos uso de la sincronización, siempre que tanto en métodos t estáticos como no estáticos, haya datos que puedan sufrir modificaciones y que no sean de tipo local, se deberán de marcar como a synchronized. v Hay un pequeño tema, dijimos que cada clase tiene un bloqueo disponible, pero es uno para la clase y uno para la instancia (static o y no static). El problema es que si un método de clase llama a un atributo estático, y el primero está sincronizado, solo se toma un a bloqueo, el de la clase. Y si otro objeto llama al método estático, y este llama al atributo de clase, solo se toma el bloqueo estático. Y l con esto ambos objetos pudieron saltear los bloqueos del otro. De más está decir que esta situación debes evitarla siempre que sea posible de manera que: b e  Los atributos estáticos solo se deben invocar desde métodos estáticos sincronizados. r  Los atributos de clase solo se deben invocar desde métodos de clase sincronizados. o l Clases multi-hilo seguro a Cuando una clase contiene métodos synchronized cuidadosamente colocados, se denomina que la clase es multi-hilo seguro . (Thread-Safe). Pero hay un problema, que la clase sea thead-safe no quita que podamos implementarla de manera incorrecta, produciendo posibles corrupciones de datos. b De manera que cuando utilicemos threads, debemos depender de la clase que llevaría a cabo la operación atómica. l o Bloqueos de la muerte g Esto se produce cuando dos bloqueos esperan que se libere el bloqueo del contrario para poder continuar. Esto generalmente es un s error muy difícil de detectar, además de que cuando trabajamos con threads, el reproducir el error es aun más complicado. p Interacción entre threads o Para comunicarse entre si, se utilizan los método: wait(), notify() y notifyAll(). t . c wait(), notify(), notifyAll() solo pueden ser invocados desde un contexto sincronizado. Un objeto no puede o ionvocar dichos métodos a menos que posea el bloqueo. m Los métodos wait() y notify() pertenecen a la clase Object. Un objeto puede tener una lista con 0 .. * (0 a muchos) objetos esperando que se les notifique cuando la ejecución de este haya terminado, o el bloqueo se haya liberado. Veamos un ejemplo:
  • 15. 15 Java World – Capítulo 7 h t //Compilación: javac -g PruebasRunnable04.java //Ejecución: java PruebasRunnable04 t p public class PruebasRunnable04 { static public void main(String[] args) { : (new PruebasRunnable04(new Object())).pruebaWait(); / } / private Object bloqueador; v a public PruebasRunnable04(Object bloqueador) { this.bloqueador = bloqueador; l } o r public void pruebaWait() { Incrementador incrementador = new Incrementador(bloqueador); c (new Thread(incrementador)).start(); r synchronized(bloqueador) { e try { a System.out.println("Esperando a que se complete el incrementador..."); bloqueador.wait(); t } catch(InterruptedException ex) {} i System.out.println("El total es: " + incrementador.getTotal()); v } } o . } class Incrementador implements Runnable { b private int contador = 0; l private Object bloqueador; public Incrementador(Object bloqueador) { o this.bloqueador = bloqueador; g } s public int getTotal() { p return contador; o } t public void run() { . synchronized(bloqueador) { for(int x = 0 ; x < 100 ; x++) { c contador++; o System.out.print("."); m try { Thread.sleep(100); } catch(InterruptedException ex){} } System.out.println(); bloqueador.notify(); } } } En el código anterior, no se ejecuta la sentencia que muestra el total hasta que Incrementador no emite el notify indicando que puede continuar. La importancia del código anterior radica en que para poder llamar al método wait del objeto bloqueador, se debe de poseer el bloqueo del mismo.
  • 16. Java World – Capítulo 7 16 Al igual que sleep(), wait() contiene una sobrecarga: wait(long milisegundos). Esto tiene como propósito poner un límite de tiempo h en la espera, ejecutando lo que ocurra primero (ya sea notify() o el tiempo ha transcurrido). t t Cuando se ejecuta un notify() no quiere decir que se libere el bloqueo. Esto se realizará una vez que se salga p del código sincronizado. : / / Utilizando notifyAll() cuando varios threads puedan estar esperando g Si más de un thread se encontraba esperando que se le notifique, al ejecutar notifyAll() todos aquellos que se encuentren en dichas u condiciones competirán por parar al estado “en ejecución”. s t Utilizando wait() en un bucle a Uno de los casos que podemos encontrar y que no hemos planteado aun es el hecho de que el notify() se ejecute antes que el wait(). v ¿Qué pasaría en esta situación?... o Simple, si un objeto estuviera esperando un notify() que no volverá a ejecutarse (esto es así por nuestra lógica del programa), el a thread estará esperando eternamente, o hasta que se genere una interrupción (InterruptedException). l b Capítulo 10 - Deployment e r Todo desarrollo en Java requiere que los archivos sean pre-compilados a bytecodes, los cuales son almacenados en archivos .class, o o porque no comprimir todos tus .class en un paquete .jar. Un recordatorio que mencionamos en el primer capítulo. Para poder compilar los archivos .java debes tener instalada alguna l versión de la JDK (Java Development Kit), no basta con tener la JRE (Java Runtime Environment) instalada. a . Compilando con con javac b Javac es el comando utilizado para poder transformar nuestros .java a .class (bytecodes). La sintaxis de este es: l javac [opciones] [archivos de código fuente] o Los elementos entre [] significan opcional. g Múltiples opciones y/o archivos de código fuente deben separarse con caracteres de espacio. s Opcion –d p Por defecto, cuando compilemos nuestros archivos en Java, el directorio destino por defecto será exactamente el mismo que el de o los códigos fuente. Para poder modificar esto existe el comando –d. t . c El directorio que especifiques mediante –d debe existir, de lo contrario generarás un error de compilación. o m
  • 17. 17 Java World – Capítulo 7 Supongamos la siguiente estructura. h t Directorio Raiz t p : source / com / v blogspot a gustavoalberola l o PruebaJavaWorld.java r classes c r Dentro de source van nuestro .java y dentro de classes nuestros .class. Si quisiéramos compilar el código anterior (tengan en cuenta que según la estructura anterior, PruebaJavaWorld.java esta dentro de e los package com, blogspot y gustavoalberola) deberíamos utilizar la sintaxis: a t Parados sobre el directorio “source” i javac –d ../classes com/blogspot/gustavoalberola/PruebaJavaWorld.java v o Esto lo que hará es crear dentro de classes la misma jerarquía de directorios, con el .class compilado a bytecode. . Ejecutando aplicaciones con java b Una vez que tenemos nuestros .class lo que necsitamos es ejecutar el programa, para ello utilizamos el comando java. Su sintaxis es: l java [opciones] clase [argumentos] o Por defecto, el comando java interpreta que lo que quieres ejecutar es un .class, de manera que no es necesario especificar la g extensión (es más, si la especificas, no podrás ejecutar tu programa). s Utilizandos las propiedades de sistema p Dentro de java tenemos una clase denominada java.util.Properties. Esta es utilizada para obtener las propiedades por defecto del o sistema operativo, el compilador de java, la jvm, y también para guardar nuestras propias propiedades. t Veamos un ejemplo simple: . c import java.util.Properties; o public class Pruebas_01 { m static public void main(String[] args) { Properties propiedades = System.getProperties(); propiedades.setProperty("MiPropiedad", "MiValor"); propiedades.list(System.out); } }
  • 18. Java World – Capítulo 7 18 Ejecutando el programa con: h java -DMyOtraPripiedad="Aun no decido que valor poner" Pruebas_01 t El resultado es algo asi: t p java.runtime.name=Java(TM) SE Runtime Environment sun.boot.library.path=C:Program FilesJavajre6bin : java.vm.version=14.3-b01 / java.vm.vendor=Sun Microsystems Inc. / java.vendor.url=http://java.sun.com/ g ... java.runtime.version=1.6.0_17-b04 u ... s java.specification.version=1.6 t user.name=gustavo a java.class.path=. MyOtraPripiedad=Aun no decido que valor poner v ... o MiPropiedad=MiValor a l b Vemos como tanto la variable que declaramos en código, como aquella que introducimos mediante –D existen en el listado de propiedades. e Manejando argumentos de la línea de comandos r o Todos losargumentos que se escriban en el momento de ejecución entran en el array de Strings del método main, empezando por el índice 0 para el primer argumento, y así sucesivamente. l a . public class Pruebas_02 { static public void main(String[] args) { b int x = 0; l for(String s : args) { System.out.println("Argumento [" + x++ + "] = " + s); o } g } } s p Ejecutando el comando o java Pruebas_02 soy1 "Y yo que?" 1234568 t . Argumento [0] = soy1 c Argumento [1] = Y yo que? o Argumento [2] = 1234568 m
  • 19. 19 Java World – Capítulo 7 Buscando otras clases h t Cuando compilamos o ejecutamos una aplicación, esta requiere de otras clases para funcionar. Supongamos que estamos en la t sección de I/O, y necesitamos la clase File, esta tendría que buscarse en java.io.File. Para ello, java realiza las siguientes acciones: p  Tanto java como javac buscan otras clases de la misma manera :  Se procede a buscar una a una las clases necesarias / o Se busca dentro de las clases que vienen estandar con J2SE / o Se busca dentro de los classpath declarados v  La búsqueda se detiene en la primer coincidencia. a  El classpath puede ser declarado de dos maneras: o Como variable del sistema operativo l o Como argumento en la línea de comandos (si se especifica, sobrescribe al classpath de sistema, solo en dicha o invocación). r c Declarando y utilizando classpaths r El classpath es una dirección a nivel de directorio en donde se buscaran las clases necesarias para compilar/ejecutar el programa. e El classpath a su vez puede estar conformado por varios classpath concatenados mediante un caracter parser que hace de a separador. t Hay que tener en cuenta que una estructura de directorio se especifica diferente según el S.O. que estemos utilizando: i  Unix: se utiliza como directorio el / y como separador el : v  Windows: se utiliza como directorio el y como separador el ;. o Un ejemplo de classpath válido para windows sería: . .classes;c:misProyectosclasses;c:; b l Muchas veces cuando ejecutamos un programa podemos toparnos con una excepción ClassNotFoundException. Esto indica que la JVM no pudo localizar alguna clase que nuestro programa requiere. o Los classpaths se recorren de izquierda a derecha. g s Cuando se utiliza el comando java, este no busca en el directorio donde esta parado las clases, solo en el p directorio de la JRE. Para que haga lo primero, es necesario especificarlo mediante la opción –classpath o – o cp. t . c Package y búsqueda o Existen dos maneras de referenciar clases desde nuestro código que se encuentran en otro package, mediante imports, o la m llamda con el nombre atómico de la clase (el package.classNombre). package com.blogspot.gustavoalberola; public class JavaWorld {}
  • 20. Java World – Capítulo 7 20 Dicha clase será almacenada en com/blogspot/gustavoalberola/JavaWorld.java. h Para referenciarlo desde otro package podemos utiliza cualquiera de las dos sentencias a continuación: t Modo de referencia atómico t p : //otro package public class OtraClase { / static public void main(String[] args) { / com.blogspot.gustavoalberola.JavaWorld javaWorld; javaWorld = new com.blogspot.gustavoalberola.JavaWorld(); g } u } s t Modo de referencia mediante imports a v o //otro package //Tambien podemos utilizar el * en vez de JavaWorld (importa todas las clases del a package) l import com.blogspot.gustavoalberola.JavaWorld; b public class OtraClase { e static public void main(String[] args) { r JavaWorld javaWorld; javaWorld = new JavaWorld(); o } l } a . Paths relativos y absolutos b l La diferencia entre un path relativo y absoluto es: o  El path relativo depende de donde se encuentra el directorio actual. Ejemplo: ../ vuelve un directorio hacia arriba. g  El path absoluto siempre referencia al mismo lugar sin importar donde se encuentre el directorio actual. Ejemplo: s c:Jre_6_0_17. p Archivos JAR o t Teniendo nuestra aplicación terminada, es probable que quieras comenzar a distribuirla. Puedes tener todos los .class en sus . respectivos directorios y distribuirlos solo de esa manera, o puedes generar unn archivo jar que contenga todos los .class. Algunas reglas con respecto a los .jar c o  Automáticamente genera un directorio META-INF. m  Automáticamente genera un archivo MANIFEST.MF dentro del directorio anterior.  Jamás introducirá ninguna de tus clases dentro del directorio META-INF.  Se copia la estructura del directorio y subdirectorios tal cual estaba en el file system.  Los comandos java y javac utilizan el .jar con una estructura de directorio normal. Cuando queremos compilar o ejecutar una clase que requiere de otra que se encuentra en un .jar, es necesario especificar en el classpath el directorio junto con el nombre y extensión del .jar. Ejemplo: java -cp=libs/JavaWorld.jar HolaJavaWorld
  • 21. 21 Java World – Capítulo 7 h t Utilizando …/jre/lib/ext t Cuando instanalamos la JRE, dentro de uno de sus directorios p encontramos jre/lib/ext. Dentro se encuentran todas las clases que java : utiliza. Si pusiéramos cualquiera de nuestras clases aquí dentro, no / necesitaríamos especificar un classpath para referenciarlas. / Esto es una práctica poco común, y solo se aconseja para casos personales, v pero no como método de distribución de un programa. También es importante saber que es muy común encontrar variables a definidas para abreviar un directorio, como por ejemplo JAVA_HOME. Si l ves en el examen esto, interpretalo como el directorio de las librerías de o java. r c Utilizando import estáticos Fin del camino r El import estático se utiliza para no tener que escribir el nombre completo Con esta última entrega concluimos la de la constante, método o atributo estático. Ejemplo: e saga de Java World SCJP. Ha sido un a camino largo y les agradecemos a todos t import static System.out; aquellos que nos estuvieron siguiendo i public class HolaMundo { todo este tiempo, a aquellos que v static public void main(String[] args) { realizaron comentarios y correcciones out.println("Hola mundo"); o } sobre los capítulos previos, y a la . } comunidad en general. b l Muchos aseguran que esto ahorra un par de tecleados a cambio de perder Nos quedan un par de cositas para subir o en la redibilidad del código. además de la compilación final de todos g los capítulos para que les sea más fácil s La llamada debe ser import static, y solo en descargarlos. p ese orden. o Esperamos que el material les sea de t . ayuda y cualquier duda o comentario c que tengan no duden en publicar sus o comentarios en el blog. m Gracias a todos!