CONCURRENCIA EN JAVA. Diseño de Sistemas Operativos Avanzados 2000/2001. Pedro Pablo Gómez Martín

Save this PDF as:
 WORD  PNG  TXT  JPG

Tamaño: px
Comenzar la demostración a partir de la página:

Download "CONCURRENCIA EN JAVA. Diseño de Sistemas Operativos Avanzados 2000/2001. Pedro Pablo Gómez Martín"

Transcripción

1 CONCURRENCIA EN JAVA Diseño de Sistemas Operativos Avanzados 2000/2001 Pedro Pablo Gómez Martín

2

3 Concurrencia en Java 1 ÍNDICE ÍNDICE... 1 INTRODUCCIÓN... 3 CREAR UNA NUEVA HEBRA... 3 FINALIZACIÓN... 5 PRIORIDADES... 6 OTROS MÉTODOS PARA EL PLANIFICADOR... 7 CLASES Y EXCEPCIONES... 8 CERROJOS...10 EXCLUSIÓN MÚTUA...10 SEÑALIZACIÓN...12 MÉTODOS DE SEÑALIZACIÓN...14 INTERBLOQUEOS...15 GRUPOS DE HEBRAS...15 OTROS MÉTODOS (DESACONSEJADOS)...15 LA MÁQUINA VIRTUAL...17 ESTRUCTURA DE LA MÁQUINA VIRTUAL...18 Synchronized(o)...21 NUEVAS HEBRAS...22 GESTIÓN DE MEMORIA...23 VARIABLES VOLATILE...24 INICIALIZACIÓN DE CLASES...24 CONCLUSIONES...25 BIBLIOGRAFÍA...26 APÉNDICE IMPLEMENTACIÓN DE LOS EJEMPLOS...27

4 2 Concurrencia en Java

5 Concurrencia en Java 3 INTRODUCCIÓN El lenguaje de programación Java proporciona, sin necesidad de ninguna otra herramienta adicional, la construcción de programas concurrentes. Para ello pone a disposición del programador la clase Thread, que permite ejecutar código en un hilo de ejecución independiente. Proporciona además métodos de sincronización entre hebras, de modo que es posible construir programas concurrentes en los que los distintos hilos de ejecución puedan sincronizarse utilizando directamente las primitivas que proporciona el lenguaje, sin necesidad de utilizar técnicas implementadas por los propios programadores. Java no dispone, no obstante, de control sobre las situaciones peligrosas en los programas concurrentes que puedan ocasionar malos funcionamientos, como por ejemplo los interbloqueos. Es responsabilidad del diseñador del sistema dar una correcta estructura al programa que tenga que implementar, de modo que no aparezcan situaciones indeseadas. Como es sabido, el lenguaje de programación Java es multiplataforma. Los programas se compilan, originandose ficheros binarios que son independientes de la plataforma. Posteriormente, en cada sistema se implementará un intérprete de esos ficheros, que los ejecutará. Para que el lenguaje sea realmente independiente de la plataforma, todos los compiladores e intérpretes de ficheros binarios deben actuar de forma similar. Eso evita que distintos compiladores admitan distintos códigos, anulando la posibilidad de la aparición de dialectos. Del mismo modo, para que la ejecución de un programa compilado sea igual en todos los sistemas, también debe quedar completamente claro la forma en la que se deben interpretar y ejecutar esos ficheros. Es el creador del lenguaje, Sun Microsystems, quien especifica tanto el lenguaje como el intérprete, en lo que se denomina la especificación del lenguaje Java, y la especificación de la máquina virtual. La mayor parte de este trabajo se basa en la última de esas dos especificaciones. Inicialmente comienzo explicando las herramientas proporcionadas por Java para permitir la programación concurrente. En ocasiones será necesario, además, hacer algun recordatorio sobre otras características del lenguaje para asegurar que la explicación queda completamente clara. No obstante no haré aquí una descripción detallada del lenguaje. Una vez visto cómo el programador puede utilizar Java para implementar programas concurrentes, veremos como consigue Java ejecutarlos. Es decir de qué mecanismos dispone la máquina virtual Java (el intérprete de los ficheros binarios) para proporcionar la concurrencia y la sincronización. CREAR UNA NUEVA HEBRA Cuando se inicia un programa Java, la máquina virtual crea una hebra inicial, que se encargará de llamar al método public static void main(string[] args) de la clase que se comienza a ejecutar. Si se desea crear una nueva hebra, es suficiente construir un nuevo objeto de la clase Thread y llamar a su método start(). Esa llamada ocasionará que se llame al método run() de la hebra, pero en un hilo de ejecución nuevo, diferente al que ejecutó la llamada al método start(). La ejecución del método run() será, por lo tanto, simultánea a la ejecución del código que siga a la llamada a start(). La implementación del método run() implementada en la clase Thread es vacía, no hace nada 1. Para construir una hebra un poco más interesante, habrá que implementar una clase que extienda a la clase Thread, y sobreescriba el método run(). Debido a la invocación dinámica propia de la programación orientada a objetos, la llamada al método start() de la clase recién creada llamará al nuevo método run() implementado. Para construir una hebra, por lo tanto, bastará con meter en el método run() el código que deseemos que se ejecute de forma independiente en una nueva hebra. 1 Esto no es cierto completamente, como veremos a continuación. No obstante, no realiza ninguna operación útil al nivel que estamos en este momento.

6 4 Concurrencia en Java Veamos un ejemplo 2. El siguiente programa: public class DosHebrasBasicas extends Thread { int cont; DosHebrasBasicas(int c) { cont = c; public void run() { while (true) { system.out.println(cont); public static void main(string[] args) { new DosHebrasBasicas(0).start(); new DosHebrasBasicas(1).start(); // class La ejecución de la aplicación anterior causa la salida por pantalla de líneas con 0 s y 1 s entrelazados. Eso se debe a que la máquina virtual distribuye el tiempo del procesador entre las dos hebras, de modo que según quién tenga el procesador se escribirá un 0 o un 1. Este modo de implementar nuevas hebras tiene una desventaja. Debido a la restricción de herencia simple impuesta por Java, sería imposible hacer clases ejecutables en hebras independientes que hereden de cualquier otra clase. Esto ocurre por ejemplo en applets. No es posible implementar la aplicación anterior en un applet de forma directa, debido a que la clase tendría que heredar simultáneamente de la clase Thread y de la clase Applet. Afortunadamente existe el interfaz Runnable. Una clase que desee implementar este interfaz deberá disponer del método: public void run(); Es posible comenzar la ejecución del método run() de cualquier objeto que implemente el interfaz en una hebra independiente. Para eso, es suficiente crear un nuevo objeto de la clase Thread, pasandole en el constructor el objeto que se desea ejecutar. Cuando se llame al método start() de esa hebra, el método que se ejecutará será, realmente, el método run() del objeto pasado en el constructor. El ejemplo anterior se implementaría: public class DosHebrasBasicas implements Runnable { int cont; DosHebrasBasicas(int c) { cont = c; public void run() { while (true) { system.out.println(cont); public static void main(string[] args) { new Thread (new DosHebrasBasicas(0)).start(); new Thread (new DosHebrasBasicas(1)).start(); // class 2 Los ejemplos suministrados no siguen exactamente este código. Puede ver más información sobre ello en el apéndice.

7 Concurrencia en Java 5 Ahora la clase no hereda de ninguna otra, por lo que la herencia queda libre para heredar, por ejemplo, de la clase Applet. También se modifica la forma de crear las hebras. Ahora es necesaria la creación de dos objetos: el objeto que implementa el interfaz, y la propia hebra que lo ejecutará. El método start() de la hebra realmente sigue ejecutando el código del método run() del objeto de la clase Thread. Se ejecutará el método run() del objeto que implementa el interfaz Runnable porque el código del run() de la hebra no está realmente vacío. En el siguiente código se esboza la parte del código de la clase Thread que nos interesa ahora mismo: public class Thread implements Runnable { /*... */ protected Runnable _target; /*... */ Thread(Runnable target) { _target = target; /*... */ public void run() { if (_target!= null) _target.run(); /*... */ Puede verse que el método run() de la hebra se encarga de llamar al método run() del objeto que implementa el interfaz Runnable, si es que se ha especificado alguno en el constructor. Si no es así, el método no hace nada. También puede verse que la clase Thread implementa el interfaz Runnable, y contiene el método run() que es el que se llama cuando se invoca al método start(), tal y como se ha dicho antes. Pero eso no debe llevar a confusión con el uso del interfaz Runnable en cualquier otra clase. La ejecución es completamente igual en los dos casos. No hay reglas de cuando usar una u otra técnica. No obstante, el uso de la herencia es solo válido cuando la clase que se desea ejecutar no tiene que heredar de ninguna otra clase. Además, se aconseja que se use herencia únicamente si hay que sobreescribir algún otro método, además del run(). Por su parte, el uso del interfaz Runnable requiere la construcción de dos objetos (la hebra y el propio objeto) para poder realizar la ejecución. FINALIZACIÓN La finalización de una hebra suele ocurrir cuando se termina de ejecutar el método run(). No obstante, hay otras tres razones por las que una hebra puede terminar: En algún momento de la ejecución del método run() se ha generado una excepción que nadie ha capturado. La excepción se propaga hasta el propio método run(). Si tampoco éste tiene un manejador para la excepción, el método run() finaliza abruptamente, terminando la ejecución de la hebra. Si se llama al método stop() o stop(excepción) de la hebra. Estos dos métodos originan que la hebra termine, y son en realidad un caso particular del anterior. Se comentan más adelante. Cuando se llama al método destroy() de la hebra. También se comenta posteriormente. En cualquiera de los casos, la hebra finaliza su ejecución, y deja de ser tenida en cuenta por el planificador.

8 6 Concurrencia en Java PRIORIDADES El planificador es la parte de la máquina virtual que se encarga de decidir qué hebra ejecutar en cada momento. La especificación de la máquina virtual no fuerza al uso de ningun algoritmo particular en la planificación de hebras. De hecho, es problema de cada implementación particular decidir si implementar por sí misma el planificador, o apoyarse en el sistema operativo subyacente. En cualquier caso si se fuerzan ciertas características que debe tener el planificador. En concreto, todas las hebras tienen una prioridad, de modo que el planificador dará más ventaja a las hebras con mayor prioridad que a las de menos. En principio, se obliga a que exista expropiación entre hebras de igual prioridad, de modo que si hay varias hebras con igual prioridad todas se ejecuten en algún momento. La especificación de la máquina virtual no obliga, sin embargo, a la expropiación de hebras de una prioridad mayor si la hebra que va a pasar a ejecutarse es de prioridad menor. Es decir, no se garantiza que hebras de prioridad baja pasen a ejecutarse si existe alguna hebra de mayor prioridad. Un sencillo ejemplo que puede utilizarse para comprobar esto es el siguiente: public class ComprobarPrioridad implements Runnable { int num; ComprobarPrioridad(int c) { num = c; public void run() { while (!parar) { system.out.println(num); cont++; public static void main(string[] args) { Thread nueva; for (int c = 0; c < 10; c++) { nueva = new Thread(new ComprobarPrioridad(c)); if (c == 0) nueva.setpriority(thread.max_priority); nueva.start(); // class Si la máquina virtual que ejecute este ejemplo no realiza expropiación en hebras de mayor prioridad para ejecutar hebras de menor prioridad, solo se ejecutará la hebra número 0, por lo que sólo se mostrará ese número en la salida estandar. Si sí se realiza expropiación, otras hebras se ejecutarán, pero, en principio, una menor cantidad de veces que la hebra 0. Del código anterior se pueden deducir algunas constantes y funciones definidas en la clase Thread para controlar la prioridad. Se definen dos funciones: setpriority(int): establece la prioridad de la hebra. Puede ocasionar la generación de una excepción de seguridad si la hebra que solicita el cambio de prioridad de otra no está autorizada a hacerlo. getpriority(): devuelve la prioridad de la hebra. Para establecer los posibles valores en el parámetro de setpriority o como resultado de getpriority, la clase Thread define tres constantes estáticas a la clase: MAX_PRIORITY (= 10): es el valor que simboliza la máxima prioridad. MIN_PRIORITY (= 1): es el valor que simboliza la mínima prioridad. NORM_PRIORITY (= 5): es el valor que simboliza la prioridad normal, la que tiene la hebra creada durante el arranque de la máquina virtual y que se encarga de ejecutar la función main().

9 Concurrencia en Java 7 Las librerías gráficas de Java AWT y Swing construyen su propia hebra, que se encargará de atender los eventos del usuario (ya sean del ratón o del teclado). Cuando, por ejemplo, se pulsa un botón, es esa hebra la que lo recoge, y la que se encarga de ejecutar el código asociado al evento. El usuario espera que sus órdenes se ejecuten instantáneamente, lo que da la impresión de un sistema rápido. Al menos, es deseable que cuando se pulse un botón, éste modifique momentáneamente su aspecto para darle al usuario la sensación de que el sistema se ha dado cuenta de su acción. Para que esto pueda realizarse, los desarrolladores de las librerías anteriores decidieron establecer a la hebra que crean una prioridad ligeramente superior a la normal (=6). Gracias a eso se logra que la interfaz gráfica responda inmediatamente, incluso aunque haya otras hebras normales ejecutandose. Cuando el usuario no realiza ninguna acción, la hebra del interfaz estará suspendida, esperando a que lleguen eventos, momento en el que se permite a esas otras hebras ejecutarse. Naturalmente, si el programa crea una hebra con una prioridad mayor que la establecida a la hebra del interfaz, ésta podría dejar de responder rápidamente. OTROS MÉTODOS PARA EL PLANIFICADOR Además del uso de las prioridades, la clase Thread implementa otros métodos con los que se puede conseguir algo de control sobre el comportamiento que toma el planificador respecto a hebras independientes. Esos métodos son: void sleep(long milis): duerme a la hebra durante al menos <milis> milisegundos. Transcurrido el tiempo, la hebra pasará a estar preparada para ejecutarse, pero eso no implica que pase inmediatamente a hacerlo (dependerá del planificador), de ahí que pueda estar más tiempo del que se especifica sin ejecutarse. void sleep(long milis, int nanos): duerme a la hebra durante al menos <milis> milisegundos y <nanos> nanosegundos. Sirve como una implementación con más precisión que la anterior. En la práctica, la implementación actual no permite tanta parecisión, y se limita a redondear los <milis> en función de los <nanos> y a llamar al método sleep anterior con el valor obtenido. void yield(): cede el procesador. Pasará a ejecutarse de nuevo el planificador, que decidirá qué otra hebra ejecutar. Los dos métodos sleep(...) anteriores pueden ocasionar la generación de la excepción InterruptedException. Ésta salta si otra hebra llama al método interrupt() de la hebra que está dormida. Cuando eso ocurre, la hebra que estaba dormida pasa inmediatamente a estar preparada, de modo que el planificador volverá a tenerla en cuenta. Para que la hebra que ejecuta el sleep(...) pueda diferenciar si ha pasado a ejecutarse por culpa de que el tiempo solicitado ha pasado, o porque alguien ha interrumpido su sueño, en este último caso el método retornará con la excepción. Con el método yield() puede verse qué estrategia sigue el planificador. Para ello se hace que cada hebra escriba su identificador, e inmediatamente ceda el control al planificador. El ejemplo siguiente hace eso, además de añadir una hebra extra que escribe su identificador y se duerme un tiempo aleatorio, para comprobar también el funcionamiento de sleep(). package Ejemplos; import java.lang.math; public class YieldSleep extends Thread { int num; boolean yield; static YieldSleep[] hebras = new YieldSleep[10]; public YieldSleep(int c, boolean yield) { num = c; this.yield = yield;

10 8 Concurrencia en Java public void run() { while (true) { if (yield) Thread.currentThread().yield(); else { try { Thread.currentThread().sleep( (long)(math.random()*1000.0)); catch (Exception e) { system.out.println(num); public static void main(string[] args) { // Establecemos la hebra actual como de maxima prioridad, para // que no pueda comenzar a ejecutarse ninguna de las hebras // hasta que no esten todas creadas. Thread.currentThread().setPriority(Thread.MAX_PRIORITY); for (int c = 0; c < hebras.length; c++) { hebras[c] = new YieldSleep(c, (c!= hebras.length - 1)); hebras[c].setpriority(thread.norm_priority); hebras[c].start(); system.out.println("todas creadas"); Este ejemplo solo sirve para ver el modo en el que la máquina virtual realiza la planificación si se ejecuta en una consola. Si se ejecuta desde un applet o una aplicación, existirá una hebra añadida, la del AWT, con mayor prioridad, y que saltará cada vez que alguna hebra trate de mostrar su identificador en un cuadro de texto, por ejemplo. El planificador tendrá por lo tanto una hebra más, por lo que el resultado puede ser desconcertante. CLASES Y EXCEPCIONES Antes de continuar, haré un rápido recordatorio sobre la estructura de clases que propone Java. Java tiene dos tipos de datos: los primitivos, y las referencias. Los primeros son los tipos básicos, (byte, short, char, int, long, float y double). Los segundos son todos los objetos, ya sean instancias de clases, o arrays. Se define una clase Object de la que deben heredar todas las demás. Cualquier otra clase que se defina tendrá, como última superclase, a la clase Object. Por tanto, todos los métodos que se definen en la clase Object son poseídos por todos los objetos. En concreto, la clase Thread tendrá los mismos métodos que posee la clase Object, y otros nuevos. Uno de los métodos heredados será, por ejemplo, tostring(), que devuelve una cadena que simboliza al objeto. Este método suele ser sobreescrito en las clases hijas, y es interesante, entre otras cosas, para implementar tablas hash. Otra clase curiosa es la clase Class. Hay un objeto de dicha clase por cada clase. Es decir, tenemos un objeto de la clase Class para la clase String, otro para la clase Thread, etc. Con esos objetos podemos obtener alguna información sobre la clase, como los métodos que tiene, sus constructores, y cosas así. También puede utilizarse para crear nuevas instancias (objetos) de esa clase. Por supuesto, y aunque resulte paradójico por la nomenglatura, la clase Class hereda de la clase Object.

11 Concurrencia en Java 9 Cuando se lanza una excepción, ésa excepción es en realidad un objeto. Todos los objetos que se lanzan como excepciones deben tener como clase a una que sea subclase de la clase Throwable. Naturalmente, ésta lo es a su vez de la clase Object. De la clase Throwable heredan dos subclases: la clase Error, y la clase Exception. Las clases que heredan de Error simbolizan excepciones graves, que en general fuerzan la finalización drástica de la ejecución. Por ejemplo, excepciones que avisan de falta de memoria para crear nuevos objetos, desbordamientos de pila, o errores internos de la implementación de la máquina virtual (estos últimos no deberían darse nunca). También incluyen aquellas excepciones que aparecen por compilaciones inconsistentes, es decir cuando desde una clase A se llama a métodos de otra clase B que ya no existen, pero que existieron en el momento en el que se compiló A. Estas excepciones pueden saltar en cualquier momento, y no suelen ser manejadas por los programas. De la otra, la clase Exception, hereda otra clase, la clase RuntimeException. De ella heredan a su vez el resto de las excepciones que puede generar la máquina virtual en tiempo de ejecución. Entre ellas están las excepciones que avisan de división por 0, de uso de una referencia a null, o de intento de acceder a posiciones de un array inválidas, que están más allá de su final. Estas excepciones suelen ser controladas más a menudo por los programas y, como las anteriores, pueden aparecer en cualquier punto del código. El programador puede definirse sus propias excepciones para avisar de situaciones incorrectas. Sun aconseja que esas excepciones de usuario hereden de la clase Exception. Estas excepciones no pueden saltar en cualquier momento, únicamente en los lugares que se definan. Todos los métodos que puedan propagar excepciones de este tipo deben indicarlo en su definión. Gracias a eso se consigue que el compilador pueda forzar al programador a un cierto control de errores. Cuando el programador quiere controlar todas las excepciones posibles que puedan saltar dentro de un bloque de código, sin importarle de qué tipo sean, habitualmente insertará un código como el siguiente: try { // Código a controlar catch (Exception e) { // Control de excepciones No suele utilizarse dentro del catch la clase Throwable en lugar de la clase Exception (a pesar de que es más general), pues incluye a las excepciones que heredan de Error, y estas suelen ser lo suficientemente graves como para que no sea aconsejable manejar. La estructura de clases descrita será por lo tanto: Object Thread Throwable Class... Error Exception... RuntimeException... Excepciones de usuario

12 10 Concurrencia en Java CERROJOS Todos las referencias (es decir todos los objetos y arrays) tienen un cerrojo asociado. Un cerrojo solo puede estar bloqueado por una hebra en cada momento. Se implementa realmente como un contador, considerandose que el cerrojo está libre cuando está a 0, y bloqueado en caso contrario. Una hebra es dueña del cerrojo si lo ha bloqueado por última vez, pasando su valor de 0 a 1. Esa hebra será la única que podrá modificar su valor, ya sea incrementandolo o decrementandolo (bloqueandolo o desbloqueandolo). El cerrojo quedará completamente libre cuando vuelva a recuperar el valor 0. Es decir quedará libre cuando la hebra que lo posea lo desbloquee tantas veces como lo haya bloqueado. Cuando una hebra trata de obtener un cerrojo que está bloqueado, ésta quedará suspendida hasta que el cerrojo sea liberado. Cada cerrojo tiene, por lo tanto, una lista de hebras suspendidas a la espera de que se libere. Cuando esto ocurre, cualquiera de ellas es despertada, y se la cede el cerrojo. La especificación de la máquina virtual no fuerza a la exisrencia de ningún tipo de planificación en la asignación de cerrojos a las hebras que estaban suspendidas, por lo que cada implementación es libre de utilizar una cola, usar las prioridades, o simplemente elegirla aleatoriamente. Los cerrojos son una capacidad proporcionada por la máquina virtual Java, pero no pueden ser accedidos de forma directa desde el lenguaje de programación. Los cerrojos los utiliza la propia máquina virtual, y el compilador, pero el lenguaje impide el acceso a ellos por parte del programador. EXCLUSIÓN MÚTUA Los cerrojos pueden utilizarse para garantizar exclusión mútua, es decir para que las hebras accedan a los recursos de forma controlada, de modo que solo una hebra sea dueña de un recurso en un determinado momento. El lenguaje Java permite al programador indicar la ejecución en exclusión mútua de partes del código. Para eso tanto el compilador como la máquina virtual trabajan de manera conjunta para que la exclusión mútua se realice. Gracias a esto, se permite un control sincronizado de acceso a recursos (por ejemplo variables), pero evitando el peligro del uso incorrecto de los cerrojos (por ejemplo que una hebra olvide liberarlos) pues éstos no pueden ser manejados de forma directa por el programador. El lenguaje Java proporciona dos modos principales de sincronización. La primera son los métodos sincronizados. En la implementación de una clase, pueden especificarse algunos (o todos) los métodos como sincronizados (synchronized). Cuando una hebra realiza una llamada a un método sincronizado, antes de que se comience a ejecutar el código del método, la hebra debe conseguir bloquear el cerrojo asociado con el objeto this que se está utilizando. Gracias a eso, solo una hebra puede estar ejecutando el código de ese método. Más aún, solo una hebra puede estar ejecutando alguno de todos los métodos sincronizados de un objeto, pues todos, antes de comenzar a ejecutarse, deben bloquear el mismo cerrojo. Hay que destacar que esto es a nivel de objetos, pues cada uno tendrá un cerrojo. Dos hebras podrán estar ejecutando el mismo método sincronizado al mismo tiempo si son de objetos diferentes (aunque de la misma clase). Esto se debe a que la entrada en un método sincronizado bloquea el cerrojo del objeto this. También los métodos de clase (static) pueden ser sincronizados. En ese caso no hay objeto this cuyo cerrojo bloquear. Lo que se hará será bloquear el cerrojo del objeto de la clase Class asociado con la clase a la que pertenece el método estático. Resumiendo: Los métodos no sincronizados se ejecutan directamente, sin esperar a poder bloquear ningún cerrojo. Los métodos de clase sincronizados se ejecutan una vez que la hebra ha bloqueado el cerrojo del objeto Class asociado con la clase. Los métodos de objeto sincronizados se ejecutan una vez que la hebra ha bloqueado el cerrojo del propio objeto this.

13 Concurrencia en Java 11 Por tanto, de un objeto podrán estar ejecutandose simultáneamente un método de clase sincronizado, un método de objeto sincronizado, un número cualquiera de métodos sin sincronizar, ya sean de clase o de objeto. Como se ha dicho, no hay un orden establecido en la entrega de cerrojos a las hebras que están esperando a bloquearlos. Por lo tanto, tampoco habrá un orden de ejecución de méotods sincronizados cuando hay varias hebras esperando. Debido a que una hebra puede bloquear tantas veces como quiera un mismo cerrojo sin suspenderse, es posible llamar a métodos sincronizados de un objeto desde otros métodos sincronizados del mismo objeto. Antes de comenzar a ejecutarse el código del nuevo método se tratará de bloquear el cerrojo. Éste estará ya bloqueado, pero por la misma hebra que trata de bloquearlo. El cerrojo aumentará por lo tanto en uno su contador sin que la hebra se suspenda. Cuando la ejecución del método finalice, el contador se decrementará, de modo que a la vuelta el estado del cerrojo será la misma que antes de llamar al método. Por último, un método sincronizado puede ser sobreescrito en las subclases como no sincronizado. De ese modo las llamadas al nuevo método no estarán controladas por el cerrojo del objeto. Si lo estarán, no obstante, las llamadas al método super.metodo(...). De igual modo, pueden sobreescribirse métodos no sincronizados por otros sincronizados en las clases hija. Los métodos sincronizados se utilizan para conseguir un acceso controlado a los objetos. Habitualmente se utilizan en objetos con estado, de modo que se evita que varias hebras traten de modificar el estado de forma simultánea, lo que ocasionaría generalmente que el objeto se quedara en un estado indefinido. También se suelen hacer en este caso sincronizados los métodos de consulta del estado, para que no puedan ser consultados durante un cambio, en el que el objeto se encuentra en un estado intermedio inválido. También se suelen utilizar métodos sincronizados en objetos que deban realizar las cosas en orden. Por ejemplo, son sincronizados los métodos en los que se envían bytes a través de un socket, para evitar problemas si dos hebras tratan de escribir simultáneamente en él. Un ejemplo sencillo es un objeto almacén, de los habituales productores/consumidores: class almacen { int[] almacen = new int[16]; int primero = 0; int cuantos = 0; synchronized public int coger() { int aux; if (cuantos == 0) return (-1); else { cuantos--; aux = primero; primero = (primero + 1) & 15; return(almacen[aux]); synchronized public boolean dejar(char val) { if (cuantos == 16) return false; int aux; aux = (primero + cuantos) & 15; cuantos++; almacen[aux] = val; return true; // almacen

14 12 Concurrencia en Java Gracias a la sincronización, la ejecución en paralelo de varias hebras productoras y consumidoras no daña al objeto. La otra forma de control de exclusión mútua que proporciona Java son los bloques sincronizados. Éstos se utilizan para hacer sincronizados secciones de código dentro de un método, pero no un método entero La forma general es:... synchronized(objeto) { // parte del código que se ejecuta en exclusión mutua.... Cuando se va a entrar en el bloque del código, la hebra intentará obtener el cerrojo del objeto, de igual modo que si se ejecutara un método sincronizado de dicho objeto. Si el cerrojo está ocupado, la hebra se suspenderá como de costumbre, y no existirán preferencias una vez que el cerrojo quede libre. Es posible bloquear el cerrojo de cualquier objeto dentro de cualquier método. Es decir no es necesario que el objeto que se bloquea sea el objeto this del método en ejecución. En vez de eso, puede bloquearse cualquier objeto. Este método de sincronización puede utilizarse, por ejemplo, para hacer sincronizadas clases cuyo código no podemos modificar, y que no lo son por no estar pensadas para ser usadas en programas concurrentes. Para eso todas las llamadas a algún método de un objeto de la clase estará encerrada en un bloque sincronizado con ese objeto. Naturalmente esto es bastante peligroso, pues es suficiente olvidar encerrar una llamada en uno de esos bloques para que todo el programa pueda resentirse. Una solución más segura es realizar una subclase de la original, con todos los métodos sincronizados. No obstante, se dispone de la primera opción por si el uso de la clase no sincronizada es esporádico (una o dos veces en todo el programa, y en sitios muy localizados) de modo que no merezca la pena realizar la subclase. Un uso más acertado de los bloques sincronizados es para ejecutar en exclusión mútua código que no pertenece claramente a un método, o para agrupar el acceso en exclusión mutua a varios recursos con un único semáforo. En este último caso, por ejemplo, podemos construir un objeto global de cualquier clase (lo lógico sería, no obstante, de la clase Object para no desperdiciar memoria) simplemente para utilizar su cerrojo. Éste lo podríamos usar, por ejemplo, para controlar el acceso en exclusión mutua a dos objetos diferentes pero, tan relacionados, como para que sea peligroso acceder a cada uno de ellos de forma simultánea. Si todos los accesos a cualquiera de los dos objetos se hace dentro de un método sincronizado del objeto global, aseguraremos que en ningún momento se esté accediendo a los dos de forma simultánea. La ejecución de un bloque sincronizado no se comienza hasta que no se bloquea el cerrojo del objeto en cuestión. Ese será el mismo cerrojo que el bloqueado cuando se ejecuta algun método sincronizado del objeto. Por lo tanto, un bloque sincronizado no comenzará a ejecutarse mientras alguina otra hebra esté ejecutando un bloque sincronizado guardado por el mismo objeto, o esté ejecutando un método sincronizado del objeto. SEÑALIZACIÓN Mediante los mecanismos anteriores se puede evitar las interferencias debido a la ejecución simultánea de varias hebras. También es posible un cierto mecanismo de comunicación entre ellas. Para ello, todos los objetos implementan los métodos wait() y notify(). A grandes rasgos, una hebra que llama al método wait() de un cierto objeto queda suspendida hasta que otra hebra llame al método notify() del mismo objeto. Por lo tanto, todos los objetos tienen una lista de hebras que están suspendidas a la espera de la llamada a notify() en ese objeto. El método notify() solo despierta a una de las hebras suspendidas, y, como con los cerrojos, la máquina virtual no obliga a la existencia de una planificación, por lo que cada implementación tiene libertad para decidir a cual despertar. Si se llama a notify() y no hay ninguna hebra suspendida esperando, la llamada no hace nada.

15 Concurrencia en Java 13 Estos métodos están pensados para avisar de cambios en el estado del objeto a las hebras que están esperando dichos cambios: synchronized void dowhencondition() { while (!condicion) wait();... synchronized void changecondition() {... notify(); En concreto, en el ejemplo de los productores/consumidores se podría utilizar wait()/notify() para no finalizar la ejecución del método hasta que no se ha añadido el elemento o hasta que no se ha obtenido. En la primera versión, cuando no había elementos y un consumidor solicitaba uno, se devolvía 1, avisando de que no había nada que dar. La versión con wait() y notify() podría evitar esto. Para eso, cuando un consumidor no puede obtener ningún elemento llamaría a wait() y se quedaría suspendida. Dentro del código de insertar elemento usado por las hebras productoras habrá una llamada a notify() de modo que cuando se añada algún elemento se despertará a una posible hebra consumidora. No obstante, aquí aparece un problema. Tanto el método que consume como el que produce son sincronizados. Cuando se ejecuta el wait(), el cerrojo del objeto está bloqueado, por lo que, en principio, cualquier llamada al método productor suspenderá a la hebra. Eso originará que no sea posible llamar a notify(), y se produzca un interbloqueo. Debido a que la finalidad de los métodos wait() y notify() es la explicada anteriormente, el comportamiento se modifica ligeramente. Todas las llamadas al método wait() de un objeto deben estar ejecutadas por una hebra que posea el cerrojo del objeto (ya sea desde dentro de un método o un bloque sincronizado). Además, la ejecución de dicho método se compone de la realización de dos operaciones de forma atómica: la liberación del cerrojo del objeto, y la suspensión de la hebra. Ambas deben realizarse seguidas, de forma inseparable. Del mismo modo, todas las hebras que llamen al método notify() deberán también estar en posesión del cerrojo del objeto. La llamada al método despierta una de las hebras en espera. Ésta no podrá comenzar a ejecutarse directamente, pues necesitará volver a bloquear el cerrojo que había liberado anteriormente. Por lo tanto, la hebra pasará de estar suspendida a la espera de un notify()a estar suspendida a la espera de conseguir el cerrojo del objeto, que tendrá bloqueado en ese momento la hebra que ha llamado al notify(). Como siempre, la máquina virtual no exige la existencia de prioridades de ningún tipo para esas hebras que deben recuperar el cerrojo que cedieron amablemente. De hecho, antes de que la hebra que ejecutó el wait() comience a ejecutarse, la condición podría modificarse (por parte de alguna otra hebra), y pasar a no cumplirse de nuevo. Debido a ello, es aconsejable utilizar la construcción while(!condicion) wait(); en lugar de if (!condicion) wait(); pues con el while repetiremos el wait() y no acabaremos hasta no estar completamente seguros de que la condición se cumple una vez que hemos recuperado el cerrojo.

16 14 Concurrencia en Java Como ya se ha dicho, es necesario que la ejecución del wait() sea atómica, aunque esté compuesta por dos operaciones. Esto es debido a que el programa puede fallar estrepitosamente si justo después de que el código del wait() libere el cerrojo (y antes de suspender la hebra metiendola en la lista de hebras en espera) otra hebra obtiene el cerrojo y llama al método notify(). Esa llamada no tendrá efecto, pues aún no hay hebras suspendidas, y la hebra que llamó al wait() pasará a estar suspendida a la espera de un notify() que llegó demasiado pronto y que, quizá, no vuelva a llegar. Debido al comportamiento de los métodos wait() y notify(), resulta peligroso realizar clases sincronizadas que actúan de puente de otras que también lo son. Más concretamente, imaginemos que, por cualquier razón, creamos una nueva clase que envuelve al almacén anterior (que usaba señalización). Esa nueva clase simplemente pasa las solicitudes a un objeto interno de la clase almacén: class puentealmacen { Almacen almaceninterno = new Almacen(); synchronized public int coger() { return almaceninterno.coger(); synchronized public boolean dejar(char val) { return almaceninterno.dejar(val); // puentealmacen Así expuesta, la clase puentealmacen no tiene ninguna razón de existir, pero podría darse el caso de que fuera necesaria la implementación de una estructura de este tipo en alguna otra situación más lógica. Aunque no lo parezca, en esta implementación hay interbloqueo. Si una hebra consumidora llama a coger() (naturalmente de la clase puentealmacen, unica forma de acceder al almacen interno), el cerrojo del puente se bloqueará. Luego se realizará una llamada al método coger() de la clase Almacen, que bloqueará a su vez su cerrojo. Debido a que todavía no hay ningún elemento, se llamaría a wait(). Esto liberaría el cerrojo del objeto interno (el almacén), pero no del externo (el puentealmacen). Cualquier hebra productora que intente llamar a dejar(...) quedará suspendida a la espera de que se libere este último cerrojo, que no se liberará nunca porque no hay forma de llamar al método notify() del objeto almacén, al ser éste privado al objeto puente. Existe por lo tanto peligro en el uso de objetos privados con señalización interna desde otras clases también sincronizadas, que habrá que controlar. MÉTODOS DE SEÑALIZACIÓN En realidad, el método wait() tiene varios hermanos, y el método notify() también. Todos ellos son finales: wait(long milis): espera hasta una notificación, o hasta que pasen <milis> milisegundos. Si el parámetro es 0, la espera es infinita. wait(long tiempo, int nanos): igual que la anterior, pero con precisión de nanosegundos. wait(): igual que wait(0). Es la explicada anteriormente. notify(): despierta a una hebra de las que están esperando. notifyall(): despierta a todas las hebras que están esperando. Todas las variantes de wait(...) pueden lanzar la excepción InterruptedException, al igual que ocurría con sleep(). La excepción se lanzará si se llama al método interrupt() de la hebra que llamó al wait(...). notify() y notifyall() son semejantes, con la diferencia de que notifyall() despierta a todas las hebras. Además, notify() es atómica, mientras que notifyall() no. Al llamar a esta última, todas las hebras suspendidas pasarán a estar preparadas para la ejecución, y competirán todas por conseguir el cerrojo que liberaron en la llamada a wait(), sin que exista ningún tipo de preferencia por ninguna de ellas.

17 Concurrencia en Java 15 Se aconseja más el uso de notifyall() que el de notify(). Si el programa está diseñado de tal forma que se asegura que sólo una hebra estará esperando a un notify() cual se use es indiferente. Sin embargo si no es así, es preferible utilizar notifyall(). Más aún, es aconsejable utilizar siempre notifyall(), pues no puede saberse con seguridad si en el futuro siempre habrá una única hebra, o será necesario modificar el comportamiento y cabrá la posibilidad de que haya más. Si en un momento dado hay más de una hebra y fuera necesario un notifyall() en lugar de un notify() podrían aparecer problemas bastante difíciles de entender. Realmente el uso de notifyall() está pensado para la posibilidad de que se utilice la espera para que se cumplan más de una condición. Podríamos tener una hebra esperando a que se cumpla una condición, y otra esperando a que se cumpla una diferente. Si se llama a notify() cuando un método hace cierta una de esas condiciones, la máquina virtual podría despertar a la hebra que está a la espera del cumplimiento de la otra condición, y al no cumplirse volvería a llamar a wait(), y la hebra que podría ya ejecutarse seguirá dormida, quizá indefinidamente. Naturalmente en este caso es aún más importante el uso de la estructura while(!condicion) wait(); en lugar de if(!condicion) wait(); INTERBLOQUEOS La existencia de varias hebras, y el uso de exclusión mútua puede ocasionar la aparición de interbloqueos, en el que dos o más hebras no pueden ejecutarse porque todas están esperando la liberación de algún recurso poseído por alguna de las otras. Java no controla el interbloqueo, de modo que es responsabilidad del diseñador de la aplicación evitarlo. GRUPOS DE HEBRAS Durante la ejecución de una aplicación, la máquina virtual ordena las hebras en grupos, construyendose una estructura jerárquica, donde cada nodo del árbol será un objeto de la clase ThreadGroup, que contendrá hebras, y quizá otros objetos ThreadGroup. Al iniciarse, la máquina virtual crea el grupo main, que contiene a la hebra main, que ejecutará el método del mismo nombre. A cada grupo de hebras se le puede establecer una prioridad, que actuará como cota superior a las prioridades de todas las hebras del grupo. Cuando una aplicación se ejecuta normalmente, la prioridad del grupo main es MAX_PRIORITY. Sin embargo, en las pruebas realizadas he visto que si lo que se ejecuta es un applet dentro de un navegador, la prioridad del grupo es menor. Más concretamente se limita a la prioridad establecida para la hebra de AWT (cuyo valor es 6, NORM_PRIORITY + 1). Además, debido a las restricciones de seguridad, esa prioridad no puede modificarse, y tampoco pueden crearse nuevos grupos (bueno, sí se puede, pero no pueden meterse nuevas hebras en ellos). De esa forma, la máxima prioridad de las hebras dentro de un applet queda limitada, y el navegador tendrá reservadas las prioridades mayores para uso propio, sin que los applets puedan interferir. Cuando cualquiera de las hebras de un grupo finaliza su método run() por la llegada de una excepción que no se captura, se llamará al método uncaughtexception(...) del grupo al que pertenece, recibiendo como parámetros la hebra que ha terminado abruptamente, y la excepción generada. Habitualmente éste se limitará a realizar un printstacktrace(...), que muestra por la salida de error información sobre la excepción. Los programas sofisticados podrían sobreescribir este método en su propia subclase de ThreadGroup que contendrá a todas sus hebras, para mostrar las excepciones en una ventana gráfica, por ejemplo. OTROS MÉTODOS (DESACONSEJADOS) La clase Thread dispone de otro grupo de métodos para controlar la ejecución, pero todos están desaconsejados (deprecated). El primero de ellos es el método stop(), que ocasiona el lanzamiento de la excepción ThreadDeath en la hebra destino. La excepción se genera sea cual sea el método que está ejecutando la hebra. La idea es que la excepción no se capture, de modo que vaya subiendo en la pila de llamadas de la hebra destino, hasta llegar al método run(), que tampoco la capturaría, finalizando la ejecución de la hebra. La excepción ThreadDeath es la única que es ignorada por el método uncaughtexception(...) de la clase ThreadGroup, de modo que el usuario no recibe ningún mensaje en la salida de error por culpa de dicha escepción.

18 16 Concurrencia en Java ThreadThead hereda intencionadamente de Error, en lugar de Exception, pues lo que se quiere es que no sea capturada, y como existe el uso generalizado de la construcción: try {... catch (Exception e) {... prefirieron que ThreadThead no heredara de Exception, a pesar de que no entra dentro de la filosofía de la clase Error. Una versión más general del método stop() es el método stop(throwable), que ocasiona el lanzamiento de la excepción especificada como parámetro. Por tanto, stop() es equivalente a stop(new ThreadThead());. Ambos métodos están desaconsejados porque son peligrosos. La generación de la excepción puede aparecer en cualquier momento, incluso en momentos críticos en los que el código no está preparado. Por ejemplo, es posible que salte dentro de un método sincronizado. La excepción ocasionará la finalización abrupta del método, lo que podría ocasionar que el objeto se quedara en un estado incorrecto, que podría ser visto por otras hebras, volviendo al sistema inestable. Naturalmente una posible solución sería que en todos los métodos sincronizados o que peligran ante la aparición de la excepción la capturaran, realizaran una limpieza rápida, y luego volvieran a generar la misma excepción, para que se propague y la hebra termine. Esta solución sin embargo es peligrosa, pues es fácil que el programador olvide realizar el control. Más aún, podría darse el caso de que una segunda excepción ThreadDeath saltara cuando se estaba tratando la primera, en cuyo caso el método saldría abruptamente antes de realizar la limpieza. Una solución más aceptada es la utilización de una variable que indica a la hebra si debe detener su ejecución: void run() { while(!acabar) {... /** * Sustituto de stop(); */ void acabar() { acabar = true; Para que la hebra responda de forma fluida, debería comprobar a menudo el valor de la variable acabar. Un peligro añadido del método stop(throwable) es que puede ocasionar que un método propague una excepción sin que el compilador pueda comprobarla. Por ejemplo: void excepcionoculta() { Thread.currentThread.stop(new MiExepcion()); El método excepcionoculta() ocasiona la propagación de una excepción (que no heredaría ni de Error ni de RuntimeException) y que el compilador no puede controlar, es decir no puede forzar a los programadores a que capturen la excepción en los lugares donde se llame al método (como haría si se lanzara con throw), pues no es consciente de ese lanzamiento. Esto rompe con toda la filosofía del compilador de forzar al programador a controlar los errores.

19 Concurrencia en Java 17 Por otro lado, el método suspend() detiene la hebra hasta que se llama a resume() de la misma hebra. También están desaconsejados. Eso se debe a que suspend() no libera el cerrojo del objeto si es llamado dentro de un método sincronizado. Por tanto el uso de suspend() y de resume() dentro de un mismo objeto sincronizado ocasiona la aparición de interbloqueo. El último es el método destroy(), que es el más radical de todos. Su llamada ocasiona la destrucción completa de la hebra, sin liberar ninguno de los cerrojos que tuviera bloqueados. Debido a su claro peligro, no está implementado. El JDK lo documenta, pero no hace nada. Curiosamente, está desaconsejado su uso ( aunque no hace nada!), pues se comportaría igual que un suspend() sin resume(). LA MÁQUINA VIRTUAL La máquina virtual es la que se encarga de interpretar y ejecutar el código binario generado por los compiladores de Java. Gracias a la existencia de la máquina virtual, los ejecutables Java son independientes de la plataforma. Pueden ser ejecutados en cualquier plataforma, siempre que ésta disponga de una implementación de la máquina virtual. Para lograr esto, Sun define la especificación de la máquina virtual, que deberán cumplir todas las implementaciones para ser válidas. Esta especificación define una serie de comportamientos y condiciones que deben cumplir todas las implementaciones, pero no se preocupa de la forma en la que ésta se haga, de su diseño, etc. La máquina virtual es muy abstracta. No es como la clásica máquina-p usada por Wirth para su lenguaje Pascal. En esta última, se definen instrucciones de bajo nivel, que tienen una implementación sencilla y rápida. La máquina virtual de Java es mucho más abstracta. Dispone de 202 instrucciones desbalanceadas, es fuertemente tipada, y dispone de instrucciones de muy alto nivel, para, por ejemplo, crear nuevos objetos. Además controla las excepciones de forma nativa, y gestiona la memoria directamente, de modo que es la propia máquina virtual la que se encarga de cargar e inicializar las clases según se van necesitando, de controlar la recogida automática de basura, etc. La mayor parte de las instrucciones son aritméticas. La máquina virtual es fuertemente tipada, de modo que existen instrucciones duplicadas. Por ejemplo, existe la instrucción de suma para enteros, long, flotantes y doubles de forma separada, cada una con su opcode. Del mismo modo existen instrucciones para restar, multiplicar, dividir, realizar el resto, operaciones lógicas sobre enteros, comparaciones, etc. También hay instrucciones tipadas para accesos a memoria (hay nada menos que 32 instrucciones load distintas). También existen instrucciones de conversión entre tipos. Existen incluso dos instrucciones diferentes que implementan de forma autómática la instrucción switch() de alto nivel. Además de los tipos básicos, también maneja de forma directa arrays y referencias a objetos. Existen instrucciones para control de arrays, para crearlos, para obtener su tamaño, para acceder a sus elementos, etc. También se controlan las referencias, existiendo una instrucción para crear nuevos objetos, cuatro para llamar a los métodos a partir de su nombre, otras tantas para acceder a los atributos, etc. Curiosamente, no existen instrucciones para liberar objetos o arrays, pues es la propia máquina virtual la que se encarga de la recolección de basura, por lo que no es necesario la liberación explícita de objetos.

20 18 Concurrencia en Java ESTRUCTURA DE LA MÁQUINA VIRTUAL La máquina virtual consta de varios bloques: Por hebra Pila de Frames PC Por JVM Heap Área de Código (text) Tabla de constantes Como se muestra, todas las hebras comparten el mismo área de código. En él, se almacena el código e información de todas las clases e interfaces, pero de forma separada. La información de cada clase o interfaz es independiente; incluso los métodos de cada clase están separados, comenzando cada uno en el offset 0. Por tanto, el área de código está dividido internamente en partes lógicas más pequeñas. Esta división hace que el área de código no tenga que ser contigua en la memoria física del sistema que ejecuta la máquina virtual. Cada clase o interfaz tiene asociada una tabla de constantes con información referenciada dentro de su código. Almacena por ejemplo el valor inicial de los campos, o cadenas con sus nombres o los de los métodos. El heap es donde se amacenan las instancias de las clases y de los arrays, es decir, los objetos dinámicos. Es una zona de memoria gestionada mediante el recogedor automático de basura, de modo que la máquina virtual directamente está encargada de gestionarla, y liberar el espacio ocupado por objetos y arrays cuyas referencias se han perdido. El heap es, naturalmente, accedido por la máquina virtual. Los programas binarios Java hacen referencia a posiciones dentro del heap, pero es la propia máquina virtual la que realiza la indexación, y obtiene la información. Por tanto, el heap puede estructurarse de cualquier forma; incluso no existe necesidad de que sea contiguo en la memoria física del sistema. Podría estar almacenado en distintos bloques, de tal forma que luego la máquina virtual acceda a los bloques correctos a partir de las referencias de los programas. En general, la máquina virtual da libertades en algunos aspectos, como puede ser el anterior de la contigüedad del heap o el área de código, y como algunas cosas en el acceso a memoria. No obstante una implementación concreta de la máquina virtual no tiene necesidad de utilizar esas libertades. En este útlimo caso, por ejemplo, no hay necesidad, naturalmente, de que una implementación utilice la posibilidad de tener el heap discontinuo, de modo que puede ser almacenado en un solo bloque. De hecho, tanto el heap como el área de código pueden ser estáticos (con un tamaño fijo), o dinámicos, de modo que la máquina virtual vaya modificando sus tamaño según lo va requiriendo el ejecutable. Habitualmente, el programa que implementa la máquina virtual aceptará parámetros para especificar el tipo de heap o área de código y su tamaño máximo. Esta similitud entre el área de código y el heap puede llevarse aún más allá. Algunas implementaciones de la máquina virtual podrían considerar que el propio área de código está dentro de la misma estructura que el heap, de forma que es controlado por de forma semejante. Esto conllevaría a que también el código estaría gestionado por el recolector automático de basura, de modo que la información sobre clases que ya no se utilizan podría ser liberada. Además de el área de código y el heap, que son globales a todas las hebras, la máquina virtual almacena un contador de programa (PC) por cada hebra. Éste le indica cual es la siguiente instrucción a ejecutar por la hebra.

Concurrencia en Java

Concurrencia en Java Concurrencia en Java Herramientas proporcionadas por Java La Máquina Virtual (JVM) Pedro Pablo Gómez Martín La clase Thread Clase principal con la que conseguir concurrencia. La llamada a su método start()

Más detalles

Federico Peinado www.federicopeinado.es

Federico Peinado www.federicopeinado.es Federico Peinado www.federicopeinado.es Depto. de Ingeniería del Software e Inteligencia Artificial disia.fdi.ucm.es Facultad de Informática www.fdi.ucm.es Universidad Complutense de Madrid www.ucm.es

Más detalles

1 HILOS (THREADS) EN JAVA

1 HILOS (THREADS) EN JAVA 1 HILOS (THREADS) EN JAVA 1.1QUÉ ES UN THREAD La Máquina Virtual Java (JVM) es un sistema multihilo. Es decir, es capaz de ejecutar varios hilos de ejecución simultáneamente. La JVM gestiona todos los

Más detalles

Java nos ofrece la clase Thread y la interfaz Runable que permiten que varios procesos estén funcionando de forma concurrente.

Java nos ofrece la clase Thread y la interfaz Runable que permiten que varios procesos estén funcionando de forma concurrente. Threads (hilos) Java nos ofrece la clase Thread y la interfaz Runable que permiten que varios procesos estén funcionando de forma concurrente. Conceptos: Proceso (thread o hilo): es un programa en ejecución

Más detalles

Programación Orientada a Eventos

Programación Orientada a Eventos Programación Orientada a Eventos Técnicas de Programación Santiago Pavón V:2012.03.13 Programas Secuénciales El flujo de ejecución del programa sigue la secuencia de sentencias que lo forman. El estado

Más detalles

Hilos en Java. Crear un Hilo. Detener un hilo. Fuente: http://www.chuidiang.com/java/hilos/hilos_java.php

Hilos en Java. Crear un Hilo. Detener un hilo. Fuente: http://www.chuidiang.com/java/hilos/hilos_java.php Fuente: http://www.chuidiang.com/java/hilos/hilos_java.php Hilos en Java A veces necesitamos que nuestro programa Java realice varias cosas simultáneamente. Otras veces tiene que realizar una tarea muy

Más detalles

Threads. La plataforma JAVA soporta programas multhreading a través del lenguaje, de librerías y del sistema de ejecución. Dos.

Threads. La plataforma JAVA soporta programas multhreading a través del lenguaje, de librerías y del sistema de ejecución. Dos. Threads Un thread es un flujo de control secuencial dentro de un programa. A los threads también se los conoce como procesos livianos ó contextos de ejecución. Un thread es similar a un programa secuencial:

Más detalles

Object 1. Threads en Java

Object 1. Threads en Java Object 1 Threads en Java Introducción En este artículo voy a explicar cómo se usan los threads en Java (también traducidos como "hilos de ejecución"). La intención no es solamente explicar cuáles son las

Más detalles

TEMA 5: Control de la Concurrencia en Java (API Estándar)

TEMA 5: Control de la Concurrencia en Java (API Estándar) TEMA 5: Control de la Concurrencia en Java (API Estándar) CONTENIDO Exclusión Mutua con código synchronized. Exclusión Mutua con métodos synchronized. Protocolos de Control de la Exclusión Mutua. Interbloqueos

Más detalles

MONITORES EN JAVA. Antonio Tomeu Control de la Concurrencia en Java: API Estándar

MONITORES EN JAVA. Antonio Tomeu Control de la Concurrencia en Java: API Estándar MONITORES EN JAVA Un monitor es un objeto que implementa acceso bajo e.m. a todos sus métodos, y provee sincronización En Java, son objetos de una clase cuyos métodos públicos son todos synchronized Un

Más detalles

Repaso de las características más importantes de la programación Java y su adaptación a Android

Repaso de las características más importantes de la programación Java y su adaptación a Android Repaso de las características más importantes de la programación Java y su adaptación a Android 1. Entorno de programación en java 2. Variables y tipos de datos 3. Operaciones y operadores 4. Clases y

Más detalles

Programación Avanzada para Sistemas de Telecomunicación. Objetos y clases. J.C. Cruellas. Objetos y clases

Programación Avanzada para Sistemas de Telecomunicación. Objetos y clases. J.C. Cruellas. Objetos y clases Programación Avanzada para Sistemas de Telecomunicación Objetos y clases Juan Carlos Cruellas cruellas@ac.upc.es Objetos y clases Concepto de objeto. Concepto de clase. Clases, objetos y programas. Clases

Más detalles

Concurrencia. Primitivas IPC con bloqueo

Concurrencia. Primitivas IPC con bloqueo Concurrencia Primitivas IPC con bloqueo Primitivas de IPC con bloqueo La solución de Peterson es correcta, pero tiene el defecto de requerir espera ocupada: Cuando un proceso quiere entrar en su región

Más detalles

Java Inicial (20 horas)

Java Inicial (20 horas) Java Inicial (20 horas) 1 Temario 1. Programación Orientada a Objetos 2. Introducción y Sintaxis Java 3. Sentencias Control Flujo 4. POO en Java 5. Relaciones entre Objetos 6. Polimorfismo, abstracción

Más detalles

Lo que necesitaremos para programar en Java, será un editor de texto o IDE y la JDK.

Lo que necesitaremos para programar en Java, será un editor de texto o IDE y la JDK. Introducción Java surgió en 1991 dentro de la empresa Sun Microsystems como un lenguaje de programación sencillo y universal destinado a electrodomésticos. La reducida potencia de cálculo y memoria de

Más detalles

2. Estructura de un programa en Java

2. Estructura de un programa en Java 24 A. García-Beltrán y J.M. Arranz 2. Estructura de un programa en Java Objetivos: a) Describir la estructura del código fuente de una aplicación Java b) Presentar los conceptos de comentario y de identificador

Más detalles

www.aprendoencasa.com Curso Introducción JAVA Pág.: 1

www.aprendoencasa.com Curso Introducción JAVA Pág.: 1 www.aprendoencasa.com Curso Introducción JAVA Pág.: 1 Introducción Java es un lenguaje basado en la programación orientada a objetos (POO), este tipo de programación va más allá del tipo de programación

Más detalles

Hebras y Sincronización en Java

Hebras y Sincronización en Java Hebras y Sincronización en Java Jonathan Makuc http://jmakuc.ublog.cl Noviembre 2008 Tópicos: 1. Introducción a hebras en Java...2 2. Hebras a través del clase Thread...3 3. Hebras a través de la interfaz

Más detalles

CONCEPTOS BASICOS DEL LENGUAJE JAVA

CONCEPTOS BASICOS DEL LENGUAJE JAVA CONCEPTOS BASICOS DEL LENGUAJE JAVA NOMENCLATURA GENERAL En Java se distinguen las letras mayúsculas y minúsculas. Las reglas del lenguaje respecto a los nombres de variables son muy amplias y permiten

Más detalles

Objetivo de aprendizaje del tema

Objetivo de aprendizaje del tema Computación II Tema 3. Identificadores, palabras clave y tipos de datos Objetivo de aprendizaje del tema Al finalizar el tema serás capaz de: Distinguir i entre modificadores d válidos y no válidos. Enumerar

Más detalles

Programación Concurrente en Java

Programación Concurrente en Java Programación Concurrente en Java Curso 2006-2007 9/2/2007 Prog. Distribuida Bajo Internet Qué es la Programación Concurrente? Diseño basado en varias actividades independientes Conceptualmente se ejecutan

Más detalles

Introducción a la Programación Orientada a Objetos

Introducción a la Programación Orientada a Objetos Introducción a la Programación Orientada a Objetos El paradigma imperativo. En un programa se tienen una serie de variables con las cuales operamos y modificamos mediante sentencias y funciones para producir

Más detalles

RESUMEN DE CONCEPTOS BASICOS DE PROGRAMACION JAVA

RESUMEN DE CONCEPTOS BASICOS DE PROGRAMACION JAVA UNED Centro Asociado de Cádiz RESUMEN DE CONCEPTOS BASICOS DE PROGRAMACION JAVA 1. OBJETOS Cualquier elemento del programa es un objeto. Un programa es un conjunto de objetos que se comunican entre sí

Más detalles

Java y JVM: programación concurrente

Java y JVM: programación concurrente Java y JVM: programación concurrente Adolfo López Díaz Escuela de Ciencias de la Computación e Informática. Universidad de Costa Rica Resumen: El lenguaje de programación Java proporciona, sin necesidad

Más detalles

Identificadores, palabras reservadas, tipos de datos, operadores aritméticos y el sistema estándar de salida en Java

Identificadores, palabras reservadas, tipos de datos, operadores aritméticos y el sistema estándar de salida en Java Identificadores, palabras reservadas, tipos de datos, operadores aritméticos y el sistema estándar de salida en Java Identificadores Las variables se utilizan en programación para almacenar temporalmente

Más detalles

Programación Concurrente en Java

Programación Concurrente en Java Hebras y monitores Departamento de Sistemas Informáticos y Programación Universidad Complutense de Madrid 21 de marzo de 2006 Threads Extendiendo la clase java.lang.thread. public class PrThread extends

Más detalles

Lenguajes de Programación Curso 04-05. Práctica 4. Herencia. Utilización de interfaces y clases abstractas. 1. Interfaces 1. 2. Clases abstractas 2

Lenguajes de Programación Curso 04-05. Práctica 4. Herencia. Utilización de interfaces y clases abstractas. 1. Interfaces 1. 2. Clases abstractas 2 Objetivos Herencia. Utilización de interfaces y clases abstractas. Índice 1. Interfaces 1 2. Clases abstractas 2 3. Collections Framework 3 3.1. Collection........................................... 3

Más detalles

Tema 2. El lenguaje de programación Java (Parte 1)

Tema 2. El lenguaje de programación Java (Parte 1) Programación en Java Tema 2. El lenguaje de programación Java (Parte 1) Luis Rodríguez Baena Facultad de Informática Elementos del lenguaje (I) El juego de caracteres. No utiliza ASCII, sino Unicode de

Más detalles

Curso de Java POO: Programación orientada a objetos

Curso de Java POO: Programación orientada a objetos Curso de Java POO: Programación orientada a objetos Luis Guerra Velasco Curso INEM 02830. Programación en Java Marzo 2010 Índice 1 Introducción a la POO 2 Herencia y polimorfismo 3 Empaquetado de proyectos

Más detalles

Benemérita Universidad Autónoma del Estado de Puebla

Benemérita Universidad Autónoma del Estado de Puebla Benemérita Universidad Autónoma del Estado de Puebla Facultad de Cs. De la Computación Programación Concurrente y Paralela Práctica de Laboratorio No. 4 Profr: María del Carmen Cerón Garnica Alumno: Roberto

Más detalles

PROGRAMACIÓN EN JAVA

PROGRAMACIÓN EN JAVA SISTEMAS INFORMÁTICOS INDUSTRIALES curso 2007-2008 PROGRAMACIÓN EN JAVA PRÁCTICA 3: Comunicación entre tareas. Modelo productor / consumidor. Objetivos Implementar una aplicación en Java en la que existan

Más detalles

Uso de excepciones en Java

Uso de excepciones en Java Uso de excepciones en Java En Java, cuando se produce un error en un método, se lanza un objeto Throwable. Cualquier método que haya llamado al método puede capturar la excepción y tomar las medidas que

Más detalles

Receta general para resolver problemas de sincronización con semáforos

Receta general para resolver problemas de sincronización con semáforos Receta general para resolver problemas de sincronización con semáforos La primera vez que te enfrentas a la tarea de implementar una solución a un problema de sincronización entre procesos, es normal que

Más detalles

Concurrencia en Java

Concurrencia en Java Concurrencia en Java Concurrencia y Distribución Programación Avanzada Posgrado en Ciencia e Ingeniería de la Computación, UNAM 1. El mecanismo de threads Una aplicación Java o applet puede contener secciones

Más detalles

Pruebas de unidad con JUnit

Pruebas de unidad con JUnit Pruebas de unidad con JUnit Cuando se implementa software, resulta recomendable comprobar que el código que hemos escrito funciona correctamente. Para ello, implementamos pruebas que verifican que nuestro

Más detalles

Tema 1. Introducción a los TAD

Tema 1. Introducción a los TAD Tema 1. Introducción a los TAD Objetivos En este tema nos ocupamos inicialmente del concepto de abstracción, dedicando la mayor atención a la abstracción de datos, estudiando aspectos relacionados con

Más detalles

Elementos léxicos del lenguaje de programación Java

Elementos léxicos del lenguaje de programación Java Elementos léxicos del lenguaje de programación Java Elementos léxicos del lenguaje de programación Java Palabras reservadas Identificadores Literales Operadores Delimitadores Comentarios Apéndices Operadores

Más detalles

Herramientas Concurrentes en JAVA

Herramientas Concurrentes en JAVA Herramientas Concurrentes en JAVA David Jesús Horat Flotats ÍNDICE 1. Introducción n a Java 2. Herramientas Concurrentes en Java 3. Lectores Escritores (2º) 4. Filósofos comensales 5. Chat usando RMI 6.

Más detalles

Benemérita Universidad Autónoma del Estado de Puebla

Benemérita Universidad Autónoma del Estado de Puebla Benemérita Universidad Autónoma del Estado de Puebla Facultad de Cs. De la Computación Programación Concurrente y Paralela Práctica de Laboratorio No. 5 Profr: María del Carmen Cerón Garnica Alumno: Roberto

Más detalles

Definición de clases: Herencia, polimorfismo, ligadura dinámica

Definición de clases: Herencia, polimorfismo, ligadura dinámica Tema 7 Definición de clases: Herencia, polimorfismo, ligadura dinámica Con alguna frecuencia es necesario definir clases de objetos entre las cuales hay elementos comunes. En una aplicación en la cual

Más detalles

Para leer la entrada de consola, lo primero que se hace es construir un Scanner que este asociado al flujo de entrada estándar System.

Para leer la entrada de consola, lo primero que se hace es construir un Scanner que este asociado al flujo de entrada estándar System. CICLO: 01/2010 Universidad Don Bosco Materia: Lenguaje de Programación III Contenido: 1-Lectura de Datos de entrada. 2-Introduccion a JOPTIONPANE. 3-Estructuras de Control. ->LECTURA DE DATOS DE ENTRADA

Más detalles

Proyecto Septiembre. Escuela Politécnica Superior Universidad Autónoma de Madrid 1

Proyecto Septiembre. Escuela Politécnica Superior Universidad Autónoma de Madrid 1 Proyecto Septiembre A. Organización de la práctica 1) Para promediar con la parte teórica de la asignatura es necesario aprobar independientemente prácticas y teoría. 2) La práctica de Septiembre se debe

Más detalles

Introducción a la programación orientada a objetos

Introducción a la programación orientada a objetos Introducción a la programación orientada a objetos 1. Introducción a la programación orientada a objetos 2. Las clases 3. El tipo Struct 4. Diferencias entre Class y Struct 5. Pilares de la Programación

Más detalles

Mensajes. Interbloqueo

Mensajes. Interbloqueo CONCURRENCIA DE PROCESOS Preparado por: Angel Chata Tintaya (angelchata@hotmail.com) Resumen Los procesos comparten variables globales, comparten y compiten por recursos, se ejecutan simultáneamente intercalándose

Más detalles

Java: Programación Multithread

Java: Programación Multithread Qué es un thread? Java: Programación Multithread Hasta el momento hemos desarrollado programas secuenciales con un único thread: en cualquier instante durante la ejecución de un programa hay un único punto

Más detalles

Modelo de Objetos Distribuidos

Modelo de Objetos Distribuidos Remote Method Invocation Modelo de Objetos Distribuidos Un objeto remoto es un objeto cuyos métodos pueden ser invocados desde otra máquina virtual de java, potencialmente en un host diferente. Modelo

Más detalles

Java en 2 horas. Rodrigo Santamaría

Java en 2 horas. Rodrigo Santamaría + Java en 2 horas Rodrigo Santamaría + Generalidades 2 Desarrollado por Sun en 1995 Hereda mucha de la sintaxis de C (1972) Fuertemente tipado y orientado a objetos Aplicaciones compiladas a bytecode Gestión

Más detalles

Concurrencia: deberes. Concurrencia: Exclusión Mutua y Sincronización. Concurrencia. Dificultades con la Concurrencia

Concurrencia: deberes. Concurrencia: Exclusión Mutua y Sincronización. Concurrencia. Dificultades con la Concurrencia Concurrencia: deberes Concurrencia: Exclusión Mutua y Sincronización Capítulo 5 Comunicación entre procesos Compartir recursos Sincronización de múltiples procesos Asignación del tiempo de procesador Concurrencia

Más detalles

Introducción a Java LSUB. 15 de enero de 2015 GSYC

Introducción a Java LSUB. 15 de enero de 2015 GSYC Introducción a LSUB GSYC 15 de enero de 2015 (cc) 2014 Laboratorio de Sistemas, Algunos derechos reservados. Este trabajo se entrega bajo la licencia Creative Commons Reconocimiento - NoComercial - SinObraDerivada

Más detalles

8. Sentencia return y métodos

8. Sentencia return y métodos 92 A. García-Beltrán y J.M. Arranz 8. Sentencia return y métodos Objetivos: a) Describir el funcionamiento de la sentencia return b) Interpretar el resultado de una sentencia return en el código fuente

Más detalles

Introducción al lenguaje JAVA

Introducción al lenguaje JAVA Universidad Autónoma de Tlaxcala Introducción al lenguaje JAVA M.C.. José Juan Hernández ndez Mora Segunda Sesión 1. Arreglos 2. Matrices 3. Clases en Java 4. Clases de Usuario en Java 5. Objetos definidos

Más detalles

Taller de Programación Estructurada en Java Tema 2. Fundamentos de la programación orientada a objetos

Taller de Programación Estructurada en Java Tema 2. Fundamentos de la programación orientada a objetos Taller de Programación Estructurada en Java Tema 2. Fundamentos de la programación orientada a objetos Ingeniero en Computación José Alfredo Cobián Campos josealfredocobian@gmail.com Facultad de Ciencias

Más detalles

6. TARJETA TELEFÓNICA: MARCACIÓN, DETECCIÓN DE PASO A FALTA, TONOS, PULSOS, INTERRUPCIÓN

6. TARJETA TELEFÓNICA: MARCACIÓN, DETECCIÓN DE PASO A FALTA, TONOS, PULSOS, INTERRUPCIÓN 6. TARJETA TELEFÓNICA: MARCACIÓN, DETECCIÓN DE PASO A FALTA, TONOS, PULSOS, INTERRUPCIÓN 6.1 INTRODUCCIÓN En este capítulo se comentan las funciones relacionadas con la tarjeta interfaz de línea telefónica

Más detalles

Introducción - por qué usarlas?(1)

Introducción - por qué usarlas?(1) Excepciones en Java Introducción - por qué usarlas?(1) En el mundo de la programación hay algo que siempre ocurre: los errores en los programas. Pero qué sucede realmente después de que ha ocurrido el

Más detalles

Multitarea en Java. Rafa Caballero - UCM

Multitarea en Java. Rafa Caballero - UCM Multitarea en Java Rafa Caballero - UCM Programa Monoproceso (monotarea) En cada momento hay una única instrucción ejecutándose Se dice que el programa es monotarea, o monoproceso o monohebra (o single

Más detalles

Clases. Java: Clases y Objetos. Clases. Clases. Modificadores de clase. Definición de una clase. Cada objeto es un ejemplar de una clase

Clases. Java: Clases y Objetos. Clases. Clases. Modificadores de clase. Definición de una clase. Cada objeto es un ejemplar de una clase Java: Clases y Objetos Clases La unidad fundamental de programación en Java es la clase Un programa Java está formado por un conjunto de clases Una clase es una plantilla que describe un conjunto de objetos

Más detalles

TEMA 5. EXCEPCIONES EN JAVA... 1 5.1 DEFINICIÓN DE EXCEPCIONES EN PROGRAMACIÓN... 2 5.2 TIPOS DE EXCEPCIONES / ERRORES Y CÓMO TRATARLOS... 10 5.

TEMA 5. EXCEPCIONES EN JAVA... 1 5.1 DEFINICIÓN DE EXCEPCIONES EN PROGRAMACIÓN... 2 5.2 TIPOS DE EXCEPCIONES / ERRORES Y CÓMO TRATARLOS... 10 5. TEMA 5. EXCEPCIONES EN JAVA... 1 5.1 DEFINICIÓN DE EXCEPCIONES EN PROGRAMACIÓN... 2 5.2 TIPOS DE EXCEPCIONES / ERRORES Y CÓMO TRATARLOS... 10 5.3 TRABAJANDO CON EXCEPCIONES: DECLARACIÓN, CONSTRUCCIÓN,

Más detalles

Implementación de monitores POSIX

Implementación de monitores POSIX Implementación de monitores POSIX Ampliación de Sistemas Operativos (prácticas) E.U. Informática en Segovia Universidad de Valladolid Programación concurrente: Problemática Presencia de condiciones de

Más detalles

Solución al Examen de Prácticas de Programación (Ingeniería Informática)

Solución al Examen de Prácticas de Programación (Ingeniería Informática) Solución al Examen de Prácticas de Programación (Ingeniería Informática) Junio 2006 Parte I. Cuestiones (3 puntos=50% nota del examen) 1) Se desea crear un conjunto de clases para representar en un programa

Más detalles

CDI Exclusión mutua a nivel alto. conceptos

CDI Exclusión mutua a nivel alto. conceptos conceptos El concepto de usar estructuras de datos a nivel alto libera al programador de los detalles de su implementación. El programador puede asumir que las operaciones están implementadas correctamente

Más detalles

EXAMEN FINAL Metodología y Programación Orientada a Objetos. Curso 2010 2011. Cuatrimestre de otoño. 17 de Enero de 2011

EXAMEN FINAL Metodología y Programación Orientada a Objetos. Curso 2010 2011. Cuatrimestre de otoño. 17 de Enero de 2011 EXAMEN FINAL Metodología y Programación Orientada a Objetos. Curso 2010 2011. Cuatrimestre de otoño. 17 de Enero de 2011 1. (0,75 PUNTOS) Identificad a continuación las sentencias que son ciertas, descartando

Más detalles

Introducción a los Tipos Abstractos de Datos

Introducción a los Tipos Abstractos de Datos Página 1 de 8 Introducción a los Tipos Abstractos de Datos Introducción: Concepto de abstracción Abstracción funcional y abstracción de datos Construcción de tipos abstractos de datos Especificación de

Más detalles

Programación Orientada a Objetos con Java

Programación Orientada a Objetos con Java Programación Orientada a Objetos con Java M.C. Jorge Eduardo Ibarra Esquer jorgeeie@uabc.mx Sobrecarga de métodos Java permite la definición de dos o más métodos que tengan el mismo nombre, dentro de la

Más detalles

SIMM: TEORÍA DE LOS S.O. I.E.S. JUAN DE LA CIERVA CURSO 2007/2008

SIMM: TEORÍA DE LOS S.O. I.E.S. JUAN DE LA CIERVA CURSO 2007/2008 SIMM: TEORÍA DE LOS S.O. I.E.S. JUAN DE LA CIERVA CURSO 2007/2008 1.- INTRODUCCIÓN A LOS PROCESOS 1.1.- Concepto 1.2.- Composición y estructura 1.3.- Estados y transiciones 2.- COMUNICACIÓN ENTRE PROCESOS

Más detalles

class Nombre_Clase extends Nombre_SuperClase { cuerpo de la clase extendida }

class Nombre_Clase extends Nombre_SuperClase { cuerpo de la clase extendida } REUTILIZACIÓN DE CLASES:MODELO DE HERENCIA EN JAVA Java soporta herencia simple pero no múltiple. Lo hace mediante el mecanismo de extensión de clase. A partir de él, una subclase se extiende (hereda)

Más detalles

INTELIGENCIA EN REDES DE COMUNICACIONES PRÁCTICA FINAL. Ignacio Ribas Ramos Miguel Flecha Lozano Ingeniería de Telecomunicaciones

INTELIGENCIA EN REDES DE COMUNICACIONES PRÁCTICA FINAL. Ignacio Ribas Ramos Miguel Flecha Lozano Ingeniería de Telecomunicaciones INTELIGENCIA EN REDES DE COMUNICACIONES PRÁCTICA FINAL BLACKJACK Ignacio Ribas Ramos Miguel Flecha Lozano Ingeniería de Telecomunicaciones 1. Explicación del juego de cartas del Blackjack El Blackjack

Más detalles

Concurrencia en.net David Jesús Horat Flotats

Concurrencia en.net David Jesús Horat Flotats Concurrencia en.net David Jesús Horat Flotats ÍNDICE 1. Introducción n a.net 2. Sincronización n en.net 2.1 Contextos sincronizados 2.2 Método M Synchronized 2.3 Regiones de código c sincronizado 2.4 Sincronización

Más detalles

PROGRAMACIÓ DIDÁCTICA: Secuanciación, Temporalización y Unidades Didácticas

PROGRAMACIÓ DIDÁCTICA: Secuanciación, Temporalización y Unidades Didácticas Departamento de Informática PROGRAMACIÓN DIDÁCTICA Curso 11-12 1 CONSEJERÍA DE EDUCACIÓN I.E.S. NERVIÓN Departamento de Informática CICLO FORMATIVO: TÉCNICO SUPERIOR EN DESARROLLO DE APLICACIONES MULTIPLATAFORMA.

Más detalles

Threads o Hilos. Marco Besteiro y Miguel Rodríguez

Threads o Hilos. Marco Besteiro y Miguel Rodríguez En.NET, cuando se lanza una aplicación se crea un proceso y dentro de este proceso un hilo de ejecución o thread para el método Main. Es posible, a la vez que se ejecuta el método Main, que la aplicación

Más detalles

1. Aplicaciones del J2SE SDK1.4.2 de Sun.

1. Aplicaciones del J2SE SDK1.4.2 de Sun. Dept Informatica Índice 1 Aplicaciones del J2SE SDK142 de Sun 1 11 javac 1 12 java 1 13 javadoc 2 14 Las que no se explican 3 2 Guía de estilo de Java 3 21 Clases 3 211 Nombres para las clases 3 212 Estructura

Más detalles

Workflow, BPM y Java Resumen de la presentación de Tom Baeyens

Workflow, BPM y Java Resumen de la presentación de Tom Baeyens Workflow, BPM y Java Resumen de la presentación de Tom Baeyens Workflow, BPM y Java Página 1 de 11 1. Introducción Tom Baeyens es el fundador y arquitecto del proyecto de JBoss jbpm, la máquina de workflow

Más detalles

EXCEPCIONES EN JAVA. Las sentencias que tratan las excepciones son try y catch. La sintaxis es:

EXCEPCIONES EN JAVA. Las sentencias que tratan las excepciones son try y catch. La sintaxis es: EXCEPCIONES EN JAVA Uno de los problemas más importantes al escribir aplicaciones es el tratamiento de los errores. Errores no previstos que distorsionan la ejecución del programa. Las excepciones de Java

Más detalles

En cualquier caso, tampoco es demasiado importante el significado de la "B", si es que lo tiene, lo interesante realmente es el algoritmo.

En cualquier caso, tampoco es demasiado importante el significado de la B, si es que lo tiene, lo interesante realmente es el algoritmo. Arboles-B Características Los árboles-b son árboles de búsqueda. La "B" probablemente se debe a que el algoritmo fue desarrollado por "Rudolf Bayer" y "Eduard M. McCreight", que trabajan para la empresa

Más detalles

Examen Junio- Grupo A Lunes 17 de Junio - Programación en C++ Pág. 1

Examen Junio- Grupo A Lunes 17 de Junio - Programación en C++ Pág. 1 Examen Junio- Grupo A Lunes 17 de Junio - Programación en C++ Pág. 1 ÍNDICE ÍNDICE... 1 1.1 Ejercicio 1: Máquina Expendedora (3.5 ptos.)... 1 1.2 Ejercicio 2: Clase Circulo (1.0 pto.)... 3 1.3 Ejercicio

Más detalles

El lenguaje de Programación C. Fernando J. Pereda <ferdy@gentoo.org>

El lenguaje de Programación C. Fernando J. Pereda <ferdy@gentoo.org> El lenguaje de Programación C Fernando J. Pereda Por qué aprender C? Portable y muy extendido Estándar (C89, C99) El lenguaje de los sistemas Un lenguaje fácil (no, no es broma) Por

Más detalles

El lenguaje de programación Java

El lenguaje de programación Java Departament d Arquitectura de Computadors El lenguaje de programación Java Java (I) Orientado a objetos Ejecutado por una maquina virtual Independiente de la plataforma Multithreaded Orientado a la red

Más detalles

Si bien Pascal-FC no trae algunas de las características de Pascal como:

Si bien Pascal-FC no trae algunas de las características de Pascal como: PROCESOS VS. HILOS: Ciclo de vida de un proceso: es prácticamente un estándar en todos los sistemas operativos. En principio el proceso no existe, es creado, luego pasa a listo (el proceso esta en condiciones

Más detalles

SIMULADOR DE SISTEMAS DE EVENTOS DISCRETOS

SIMULADOR DE SISTEMAS DE EVENTOS DISCRETOS SIMULADOR DE SISTEMAS DE EVENTOS DISCRETOS MANUAL DE USUARIO 1.1 Introducción. El simulador de sistemas de eventos discretos está compuesto por dos aplicaciones: el Simulador de redes de Petri y el Simulador

Más detalles

Modulo 1 El lenguaje Java

Modulo 1 El lenguaje Java Modulo 1 El lenguaje Java 13 - Codificación en Java Una de las grandes diferencias entre Java y Pascal en cuando a la codificación es que Java se trata de un lenguaje de los llamados case sensitive Esto

Más detalles

Programación en Java. Hola Jesus. Primera clase del curso de Java

Programación en Java. Hola Jesus. Primera clase del curso de Java Programación en Java Un programa o aplicación Java se compone de un conjunto de clases que contienen variables de diversos tipos utilizadas para almacenar datos, y métodos que implementan código capaz

Más detalles

GESTIÓN DE EXCEPCIONES EN JAVA. CAPTURA CON BLOQUES TRY CATCH Y FINALLY. EJEMPLOS RESUELTOS. (CU00927C)

GESTIÓN DE EXCEPCIONES EN JAVA. CAPTURA CON BLOQUES TRY CATCH Y FINALLY. EJEMPLOS RESUELTOS. (CU00927C) APRENDERAPROGRAMAR.COM GESTIÓN DE EXCEPCIONES EN JAVA. CAPTURA CON BLOQUES TRY CATCH Y FINALLY. EJEMPLOS RESUELTOS. (CU00927C) Sección: Cursos Categoría: Lenguaje de programación Java nivel avanzado I

Más detalles

JavaScript. Contenidos. Introducción El lenguaje Validación de formularios. Programación en Internet 2005-2006. DLSI - Universidad de Alicante 1

JavaScript. Contenidos. Introducción El lenguaje Validación de formularios. Programación en Internet 2005-2006. DLSI - Universidad de Alicante 1 Departamento de Lenguajes y Sistemas Informáticos JavaScript Programación en Internet Curso 2005-2006 Contenidos Introducción El lenguaje Validación de formularios DLSI - Universidad de Alicante 1 Introducción

Más detalles

Ejercicios de evaluación de fundamentos de programación en Java

Ejercicios de evaluación de fundamentos de programación en Java Ejercicios de evaluación de fundamentos de programación en Java Jorge Martínez Ladrón de Guevara Editorial EME ISBN 978-84-96285-40-8 Contenido 1. Introducción a Java... 1 Test de evaluación...1 Ejercicios...4

Más detalles

Introducción... 1 Qué es Java?... 1 Compilando a Bytecode... 1 Usando jgrasp Para Hacer el Trabajo Sucio... 5 El Entorno de jgrasp...

Introducción... 1 Qué es Java?... 1 Compilando a Bytecode... 1 Usando jgrasp Para Hacer el Trabajo Sucio... 5 El Entorno de jgrasp... Contenido Introducción... 1 Qué es Java?... 1 Compilando a Bytecode... 1 Usando jgrasp Para Hacer el Trabajo Sucio... 5 El Entorno de jgrasp... 5 Introducción Es tiempo de hablar en detalle de lo que significa

Más detalles

Software Criptográfico FNMT-RCM

Software Criptográfico FNMT-RCM Software Criptográfico FNMT-RCM ÍNDICE 1. DESCARGA E INSTALACIÓN DEL SOFTWARE 2. EXPORTACIÓN DE CERTIFICADOS EN MICROSOFT INTERNET EXPLORER 3. IMPORTACIÓN DEL CERTIFICADO A LA TARJETA CRIPTOGRÁFICA -2-

Más detalles

Tipos de variables en Visual Basic (integer, single, double, string, object, etc.). Ejemplos. (CU00308A)

Tipos de variables en Visual Basic (integer, single, double, string, object, etc.). Ejemplos. (CU00308A) aprenderaprogramar.com Tipos de variables en Visual Basic (integer, single, double, string, object, etc.). Ejemplos. (CU00308A) Sección: Cursos Categoría: Curso Visual Basic Nivel I Fecha revisión: 2029

Más detalles

Programación orientada a objetos

Programación orientada a objetos Repaso Programación orientada a objetos Curso INEM. Programación en Java Santiago Muelas Pascual smuelas@fi.upm.es! Clase! Objeto! Atributo o variable de instancia! Método! Instanciar/crear un objeto!

Más detalles

CÁTEDRA DE LENGUAJE DE PROGRAMACIÓN JAVA 2014

CÁTEDRA DE LENGUAJE DE PROGRAMACIÓN JAVA 2014 CÁTEDRA DE LENGUAJE DE PROGRAMACIÓN JAVA 2014 Ings. Mario Bressano & Miguel Iwanow ENVÍO 01/2014 Introducción al Lenguaje Java Paquetes Un Paquete en Java es un contenedor de clases que permite agrupar

Más detalles

Práctica 3 mtp. metodoloxía e tecnoloxía da programación. Presentar detalles básicos sobre la sintaxis del lenguaje de programación Java.

Práctica 3 mtp. metodoloxía e tecnoloxía da programación. Presentar detalles básicos sobre la sintaxis del lenguaje de programación Java. Práctica 3 mtp metodoloxía e tecnoloxía da programación Objetivos: Duración: Presentar detalles básicos sobre la sintaxis del lenguaje de programación Java. 1 semana 1.- Identificadores Los identificadores

Más detalles

Prácticas de Programación

Prácticas de Programación Prácticas de Programación Tema 1. Introducción al análisis y diseño de programas Tema 2. Clases y objetos Tema 4. Tratamiento de errores Tema 5. Aspectos avanzados de los tipos de datos Tema 6. Modularidad

Más detalles

Arquitectura de Aplicaciones

Arquitectura de Aplicaciones 1 Capítulo 13: Arquitectura de aplicaciones. - Sommerville Contenidos del capítulo 13.1 Sistemas de procesamiento de datos 13.2 Sistemas de procesamiento de transacciones 13.3 Sistemas de procesamiento

Más detalles

Programación Concurrente y Paralela. P(S) ; sección crítica P(S);

Programación Concurrente y Paralela. P(S) ; sección crítica P(S); 2.5.2 Monitores Los semáforos, a pesar de su sencillez de uso, son el equivalente a las instrucciones goto y el manejo de apuntadores en los lenguajes de programación imperativos: son muy susceptibles

Más detalles

Módulo 1 El lenguaje Java

Módulo 1 El lenguaje Java Módulo 1 El lenguaje 1.1 Presentación de es un lenguaje de programación desarrollado por la empresa Sun Microsystems en 1991 como parte de un proyecto secreto de investigación llamado Green Proyect, con

Más detalles

Un comité de la organización ANSI (American National Standards Institute) aborda la problemática del almacenamiento de datos para su procesamiento en

Un comité de la organización ANSI (American National Standards Institute) aborda la problemática del almacenamiento de datos para su procesamiento en 15/05/2012 1 Un comité de la organización ANSI (American National Standards Institute) aborda la problemática del almacenamiento de datos para su procesamiento en aplicaciones informáticas en 1975. 2 Como

Más detalles

Java en 3 horas. Ampliación de Sistemas Operativos. Rodrigo Santamaría

Java en 3 horas. Ampliación de Sistemas Operativos. Rodrigo Santamaría Java en 3 horas Ampliación de Sistemas Operativos Rodrigo Santamaría Generalidades Desarrollado por Sun Hereda mucha de la sintaxis de C (1972) Fuertemente tipado y orientado a objetos Aplicaciones compiladas

Más detalles

Tema 11. Soporte del Sistema Operativo 11.1. REQUERIMIENTOS DE LOS SISTEMAS OPERATIVOS. 11.1.1. MULTIPROGRAMACIÓN.

Tema 11. Soporte del Sistema Operativo 11.1. REQUERIMIENTOS DE LOS SISTEMAS OPERATIVOS. 11.1.1. MULTIPROGRAMACIÓN. Tema 11 Soporte del Sistema Operativo 11.1. REQUERIMIENTOS DE LOS SISTEMAS OPERATIVOS. El sistema operativo es básicamente un programa que controla los recursos del computador, proporciona servicios a

Más detalles

Q-flow 3.1: Introducción a Q-flow

Q-flow 3.1: Introducción a Q-flow Q-flow 3.1: Introducción a Q-flow Código del manual: Qf310001ESP Versión: 1.1 Se aplica a: Q-flow 3.1 Última revisión: 13/12/2010 i Q f 3 1 0 0 0 1 E S P v 1. 1 Q - f l o w 3.1 Introducción a Q-flow Urudata

Más detalles

Programación en Java. Programación en OO

Programación en Java. Programación en OO Programación en OO Lección 4:Programación en OO 1. Herencia 2. Modificadores de Acceso 3. Interfaces Herencia Es la acción en la que una clase obtiene los métodos y propiedades definidos en otra clase,

Más detalles

Excepciones. Gonzalo Méndez - Dpto. Ingeniería de Software e Inteligencia Artificial. Excepciones

Excepciones. Gonzalo Méndez - Dpto. Ingeniería de Software e Inteligencia Artificial. Excepciones Programación Orientada a Objetos en Java Curso 2006-2007 Tema 6 Excepciones Gonzalo Méndez Pozo Dpto. de Ingeniería de Software e Inteligencia Artificial Universidad Complutense de Madrid Qué son? Excepciones

Más detalles