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

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

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 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

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

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

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

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

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

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

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

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

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

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

Adaptación al NPGC. Introducción. NPGC.doc. Qué cambios hay en el NPGC? Telf.: 93.410.92.92 Fax.: 93.419.86.49 e-mail:atcliente@websie.

Adaptación al NPGC. Introducción. NPGC.doc. Qué cambios hay en el NPGC? Telf.: 93.410.92.92 Fax.: 93.419.86.49 e-mail:atcliente@websie. Adaptación al NPGC Introducción Nexus 620, ya recoge el Nuevo Plan General Contable, que entrará en vigor el 1 de Enero de 2008. Este documento mostrará que debemos hacer a partir de esa fecha, según nuestra

Más detalles

Transacciones y bloqueos en SQL-Server

Transacciones y bloqueos en SQL-Server Transacciones y bloqueos en SQL-Server (Información para el uso desde Axapta) Introducción En este documento vamos a intentar explicar cuatro conceptos básicos acerca de las transacciones y los bloqueos

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

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

Capítulo 9. Archivos de sintaxis

Capítulo 9. Archivos de sintaxis Capítulo 9 Archivos de sintaxis El SPSS permite generar y editar archivos de texto con sintaxis SPSS, es decir, archivos de texto con instrucciones de programación en un lenguaje propio del SPSS. Esta

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

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

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

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

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

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

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

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

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

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

MANUAL DE AYUDA MODULO TALLAS Y COLORES

MANUAL DE AYUDA MODULO TALLAS Y COLORES MANUAL DE AYUDA MODULO TALLAS Y COLORES Fecha última revisión: Enero 2010 Índice TALLAS Y COLORES... 3 1. Introducción... 3 CONFIGURACIÓN PARÁMETROS TC (Tallas y Colores)... 3 2. Módulos Visibles... 3

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

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

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

En términos generales, un foro es un espacio de debate donde pueden expresarse ideas o comentarios sobre uno o varios temas.

En términos generales, un foro es un espacio de debate donde pueden expresarse ideas o comentarios sobre uno o varios temas. 1 de 18 Inicio Qué es un foro En términos generales, un foro es un espacio de debate donde pueden expresarse ideas o comentarios sobre uno o varios temas. En el campus virtual, el foro es una herramienta

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

Uso de Visual C++ Pre-Practica No. 3

Uso de Visual C++ Pre-Practica No. 3 Pre-Practica No. 3 Uso de Visual C++ Microsoft Visual C++ 2010 es una versión de Visual Studio específica para el lenguaje de programación C++. Es un entorno de desarrollo muy completo y profesional. Por

Más detalles

AGREGAR UN EQUIPO A UNA RED Y COMPARTIR ARCHIVOS CON WINDOWS 7

AGREGAR UN EQUIPO A UNA RED Y COMPARTIR ARCHIVOS CON WINDOWS 7 Tutoriales de ayuda e información para todos los niveles AGREGAR UN EQUIPO A UNA RED Y COMPARTIR ARCHIVOS CON WINDOWS 7 Como agregar a una red existente un equipo con Windows 7 y compartir sus archivos

Más detalles

Tema 4. Gestión de entrada/salida

Tema 4. Gestión de entrada/salida Tema 4. Gestión de entrada/salida 1. Principios de la gestión de E/S. 1.Problemática de los dispositivos de E/S. 2.Objetivos generales del software de E/S. 3.Principios hardware de E/S. 1. E/S controlada

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

TPVFÁCIL. Caja Real. Definiciones.

TPVFÁCIL. Caja Real. Definiciones. TPVFÁCIL. Caja Real. TPVFÁCIL incluye desde la versión 3.3.2 la posibilidad de manejar dos cajas, la Caja Real y la Caja normal. La idea es esconder los datos de caja que pueden alcanzar los usuarios no

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

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

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

CASO PRÁCTICO. ANÁLISIS DE DATOS EN TABLAS DINÁMICAS

CASO PRÁCTICO. ANÁLISIS DE DATOS EN TABLAS DINÁMICAS CASO PRÁCTICO. ANÁLISIS DE DATOS EN TABLAS DINÁMICAS Nuestra empresa es una pequeña editorial que maneja habitualmente su lista de ventas en una hoja de cálculo y desea poder realizar un análisis de sus

Más detalles

Oficina Online. Manual del administrador

Oficina Online. Manual del administrador Oficina Online Manual del administrador 2/31 ÍNDICE El administrador 3 Consola de Administración 3 Administración 6 Usuarios 6 Ordenar listado de usuarios 6 Cambio de clave del Administrador Principal

Más detalles

COPIAS DE SEGURIDAD AUTOMÁTICAS DE DIRECCIONES CALLEÇPAÑA

COPIAS DE SEGURIDAD AUTOMÁTICAS DE DIRECCIONES CALLEÇPAÑA COPIAS DE SEGURIDAD AUTOMÁTICAS DE DIRECCIONES CALLEÇPAÑA Autor: Carlos Javier Martín González. Licenciado en Física Teórica por la Universidad Autónoma de Madrid. Analista programador y funcional. Desarrollador

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

Servicio de Alta, Baja, Modificación y Consulta de usuarios Medusa

Servicio de Alta, Baja, Modificación y Consulta de usuarios Medusa Documentos de Proyecto Medusa Documentos de: Serie: Manuales Servicio de Alta, Baja, Modificación y Consulta del documento: Fecha 22 de febrero de 2007 Preparado por: José Ramón González Luis Aprobado

Más detalles

Mantenimiento Limpieza

Mantenimiento Limpieza Mantenimiento Limpieza El programa nos permite decidir qué tipo de limpieza queremos hacer. Si queremos una limpieza diaria, tipo Hotel, en el que se realizan todos los servicios en la habitación cada

Más detalles

Introducción a la Firma Electrónica en MIDAS

Introducción a la Firma Electrónica en MIDAS Introducción a la Firma Electrónica en MIDAS Firma Digital Introducción. El Módulo para la Integración de Documentos y Acceso a los Sistemas(MIDAS) emplea la firma digital como método de aseguramiento

Más detalles

Una vez que tengamos el padrón de un determinado tributo con todos sus datos actualizados, podemos generar los recibos de ese padrón.

Una vez que tengamos el padrón de un determinado tributo con todos sus datos actualizados, podemos generar los recibos de ese padrón. 11. RECIBOS. Desde esta opción de Menú vamos a completar el proceso de gestión de los diferentes tributos, generando recibos, informes de situación, impresiones, etc. 11.1. GENERACIÓN DE RECIBOS. Una vez

Más detalles

Sistema de Facturación de Ventas WhitePaper Enero de 2007

Sistema de Facturación de Ventas WhitePaper Enero de 2007 Sistema de Facturación de Ventas WhitePaper Enero de 2007 Ronda Guglielmo Marconi, 9 Parque Tecnológico 46980 Paterna Valencia Spain T +34 96 338 99 66 ventas@preference.es Please Recycle PrefSuite Document

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

Tema 6. Reutilización de código. Programación 2015-2016. Programación - Tema 6: Reutilización de código

Tema 6. Reutilización de código. Programación 2015-2016. Programación - Tema 6: Reutilización de código Tema 6 Reutilización de código Programación 2015-2016 Programación - Tema 6: Reutilización de código 1 Tema 6. Reutilización de código Modularidad. Implementación de métodos. Uso de métodos. Programación

Más detalles

I. Introducción a la programación orientada a objetos y al lenguaje JAVA Colegio Reuven Feuerstein Javier Navarro

I. Introducción a la programación orientada a objetos y al lenguaje JAVA Colegio Reuven Feuerstein Javier Navarro I. Introducción a la programación orientada a objetos y al lenguaje JAVA Colegio Reuven Feuerstein Javier Navarro Utilizando Clases Definidas en Java La manera de utilizar una clase previamente definida

Más detalles

Sitios remotos. Configurar un Sitio Remoto

Sitios remotos. Configurar un Sitio Remoto Sitios remotos Definir un sitio remoto significa establecer una configuración de modo que Dreamweaver sea capaz de comunicarse directamente con un servidor en Internet (por eso se llama remoto) y así poder

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

19 4.1.1.0 4 04/05/2009

19 4.1.1.0 4 04/05/2009 Soluciones Informáticas Descripción: Como utilizar la Agenda de Visitas Objetivos: Al finalizar este tutorial el usuario será capaz de utilizar la Agenda de Visitas con sus diferentes opciones: asignar

Más detalles

UAM MANUAL DE EMPRESA. Universidad Autónoma de Madrid

UAM MANUAL DE EMPRESA. Universidad Autónoma de Madrid MANUAL DE EMPRESA Modo de entrar en ÍCARO Para comenzar a subir una oferta de empleo, el acceso es a través del siguiente enlace: http://icaro.uam.es A continuación, aparecerá la página de inicio de la

Más detalles

MANUAL DE USUARIO DE LA APLICACIÓN DE ACREDITACION DE ACTIVIDADES DE FORMACION CONTINUADA. Perfil Entidad Proveedora

MANUAL DE USUARIO DE LA APLICACIÓN DE ACREDITACION DE ACTIVIDADES DE FORMACION CONTINUADA. Perfil Entidad Proveedora MANUAL DE USUARIO DE LA APLICACIÓN DE ACREDITACION DE ACTIVIDADES DE FORMACION CONTINUADA Perfil Entidad Proveedora El objetivo del módulo de Gestión de Solicitudes vía Internet es facilitar el trabajo

Más detalles

LiLa Portal Guía para profesores

LiLa Portal Guía para profesores Library of Labs Lecturer s Guide LiLa Portal Guía para profesores Se espera que los profesores se encarguen de gestionar el aprendizaje de los alumnos, por lo que su objetivo es seleccionar de la lista

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

App para realizar consultas al Sistema de Información Estadística de Castilla y León

App para realizar consultas al Sistema de Información Estadística de Castilla y León App para realizar consultas al Sistema de Información Estadística de Castilla y León Jesús M. Rodríguez Rodríguez rodrodje@jcyl.es Dirección General de Presupuestos y Estadística Consejería de Hacienda

Más detalles

Trey-SAT Pag. 1. Manual de usuario

Trey-SAT Pag. 1. Manual de usuario Trey-SAT Pag. 1 Manual de usuario Trey-SAT Pag. 2 Modulo SAT : Servicio de asistencia técnica TREY-SAT es un potente módulo para el servicio de asistencia técnica, completamente integrado a la Gestión

Más detalles

COMPROBACIONES BÁSICAS PARA EL USO DE FIRMA EN EL RTC

COMPROBACIONES BÁSICAS PARA EL USO DE FIRMA EN EL RTC TITULO: COMPROBACIONES BÁSICAS PARA EL USO DE FIRMA EN EL RTC RESUMEN: La idea de este documento es mostrar una serie de acciones y ayudas básicas para intentar determinar y solucionar problemas en la

Más detalles

1 (2 5 puntos) Responda con brevedad y precisión a las siguientes preguntas:

1 (2 5 puntos) Responda con brevedad y precisión a las siguientes preguntas: Universidad de Las Palmas de Gran Canaria Escuela Universitaria de Informática Facultad de Informática Sistemas Operativos Examen parcial, 11 de mayo de 2002 SOLUCIONES Calificación 1 2 3 4 5 1 (2 5 puntos)

Más detalles

Programa diseñado y creado por 2014 - Art-Tronic Promotora Audiovisual, S.L.

Programa diseñado y creado por 2014 - Art-Tronic Promotora Audiovisual, S.L. Manual de Usuario Programa diseñado y creado por Contenido 1. Acceso al programa... 3 2. Opciones del programa... 3 3. Inicio... 4 4. Empresa... 4 4.2. Impuestos... 5 4.3. Series de facturación... 5 4.4.

Más detalles

ICARO MANUAL DE LA EMPRESA

ICARO MANUAL DE LA EMPRESA ICARO MANUAL DE LA EMPRESA 1. ENTRANDO EN ICARO Para acceder al Programa ICARO tendremos que entrar en http://icaro.ual.es Figura 1 A continuación os aparecerá la página de Inicio del aplicativo ICARO.

Más detalles

19. Packages o paquetes

19. Packages o paquetes Programación orientada a objetos con Java 201 19. Packages o paquetes Objetivos: a) Definir el concepto de paquete b) Interpretar el código fuente de una aplicación Java donde se utilicen paquetes c) Construir

Más detalles

TPV Táctil. Configuración y Uso. Rev. 1.2 21/01/09

TPV Táctil. Configuración y Uso. Rev. 1.2 21/01/09 Configuración y Uso Rev. 1.2 21/01/09 Rev. 2.0 20100616 1.- Ruta de Acceso a Imágenes. 2.- Estructuración de los Artículos. 3.- Creación de Grupos de Familias. 4.- Creación de Familias de Ventas. 5.- Creación

Más detalles

MANUAL DE AYUDA HERRAMIENTA DE APROVISIONAMIENTO

MANUAL DE AYUDA HERRAMIENTA DE APROVISIONAMIENTO MANUAL DE AYUDA HERRAMIENTA DE APROVISIONAMIENTO Fecha última revisión: Junio 2011 INDICE DE CONTENIDOS HERRAMIENTA DE APROVISIONAMIENTO... 3 1. QUÉ ES LA HERRAMIENTA DE APROVISIONAMIENTO... 3 HERRAMIENTA

Más detalles

Manual Gran Hotel. N. Res: Número de Reserva que el programa le ha adjudicado de forma automática

Manual Gran Hotel. N. Res: Número de Reserva que el programa le ha adjudicado de forma automática Recepción Check-in Pantalla para la entrega de llaves y Check-in del cliente. 1. Llegadas del día En la parte de la izquierda de la pantalla de da un listado con todas las reservas existentes con fecha

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

Primer Parcial Septiembre 5 de 2009

Primer Parcial Septiembre 5 de 2009 Primer Parcial Septiembre 5 de 2009 Algoritmos y Lenguajes II Reglas del juego Tal como se le dijo antes, durante este examen usted no puede pedir ABSOLUTAMENTE nada prestado a sus compañeros, ni hablar

Más detalles

GENERACIÓN DE ANTICIPOS DE CRÉDITO

GENERACIÓN DE ANTICIPOS DE CRÉDITO GENERACIÓN DE ANTICIPOS DE CRÉDITO 1 INFORMACIÓN BÁSICA La aplicación de generación de ficheros de anticipos de crédito permite generar fácilmente órdenes para que la Caja anticipe el cobro de créditos

Más detalles

GENERACIÓN DE TRANSFERENCIAS

GENERACIÓN DE TRANSFERENCIAS GENERACIÓN DE TRANSFERENCIAS 1 INFORMACIÓN BÁSICA La aplicación de generación de ficheros de transferencias permite generar fácilmente órdenes para que la Caja efectúe transferencias, creando una base

Más detalles

El control de la tesorería consiste en gestionar desde la aplicación los cobros y pagos generados a partir de las facturas de venta y de compra.

El control de la tesorería consiste en gestionar desde la aplicación los cobros y pagos generados a partir de las facturas de venta y de compra. Gestión de la tesorería y del riesgo El control de la tesorería consiste en gestionar desde la aplicación los cobros y pagos generados a partir de las facturas de venta y de compra. En este manual nos

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

LABORATORIO Nº 2 GUÍA PARA REALIZAR FORMULAS EN EXCEL

LABORATORIO Nº 2 GUÍA PARA REALIZAR FORMULAS EN EXCEL OBJETIVO Mejorar el nivel de comprensión y el manejo de las destrezas del estudiante para utilizar formulas en Microsoft Excel 2010. 1) DEFINICIÓN Una fórmula de Excel es un código especial que introducimos

Más detalles

Tutorial Básico de vbscript

Tutorial Básico de vbscript Tutorial Básico de vbscript Bueno, primero aclarar que este tutorial, pretende explicar de manera básica las distintas instrucciones aplicadas en visual basic script (vbs de aquí en más), para que así

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

Base de datos en Excel

Base de datos en Excel Base de datos en Excel Una base datos es un conjunto de información que ha sido organizado bajo un mismo contexto y se encuentra almacenada y lista para ser utilizada en cualquier momento. Las bases de

Más detalles

Guías _SGO. Gestione administradores, usuarios y grupos de su empresa. Sistema de Gestión Online

Guías _SGO. Gestione administradores, usuarios y grupos de su empresa. Sistema de Gestión Online Guías _SGO Gestione administradores, usuarios y grupos de su empresa Sistema de Gestión Online Índice General 1. Parámetros Generales... 4 1.1 Qué es?... 4 1.2 Consumo por Cuentas... 6 1.3 Días Feriados...

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

Manual Oficina Web de Clubes (FBM)

Manual Oficina Web de Clubes (FBM) Manual Oficina Web de Clubes (FBM) INTRODUCCIÓN: La Oficina Web de Clubes de Intrafeb es la oficina virtual desde la que un club podrá realizar las siguientes operaciones durante la temporada: 1. Ver información

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

Escritorio remoto y VPN. Cómo conectarse desde Windows 7

Escritorio remoto y VPN. Cómo conectarse desde Windows 7 Escritorio remoto y VPN. Cómo conectarse desde Windows 7 Hay ocasiones en las que es necesario conectarnos a un equipo informático situado a mucha distancia de donde nos encontramos para realizar sobre

Más detalles

MINI MANUAL PARA CREAR FORMULARIOS CON PHP Marzo 2007

MINI MANUAL PARA CREAR FORMULARIOS CON PHP Marzo 2007 MINI MANUAL PARA CREAR FORMULARIOS CON PHP Marzo 2007 Servicio de Informática y Comunicaciones Para poder diseñar un formulario y que éste nos envíe los resultados a nuestro correo electrónico, necesitamos

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

Manual para la utilización de PrestaShop

Manual para la utilización de PrestaShop Manual para la utilización de PrestaShop En este manual mostraremos de forma sencilla y práctica la utilización del Gestor de su Tienda Online mediante Prestashop 1.6, explicaremos todo lo necesario para

Más detalles

SERVIDOR WEB PARA ACCESO EN TIEMPO REAL A INFORMACIÓN METEOROLÓGICA DISTRIBUIDA

SERVIDOR WEB PARA ACCESO EN TIEMPO REAL A INFORMACIÓN METEOROLÓGICA DISTRIBUIDA SERVIDOR WEB PARA ACCESO EN TIEMPO REAL A INFORMACIÓN METEOROLÓGICA DISTRIBUIDA E. SÁEZ, M. ORTIZ, F. QUILES, C. MORENO, L. GÓMEZ Área de Arquitectura y Tecnología de Computadores. Departamento de Arquitectura

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

WINDOWS 98/Me EL EXPLORADOR DE WINDOWS IV

WINDOWS 98/Me EL EXPLORADOR DE WINDOWS IV 10 EL EXPLORADOR DE WINDOWS IV Operaciones con discos Desde el Explorador, también puede ejecutar diversas operaciones sobre discos completos. Aunque, desde aquí, es posible formatear discos duros, lo

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

MANUAL DE AYUDA TAREA PROGRAMADA COPIAS DE SEGURIDAD

MANUAL DE AYUDA TAREA PROGRAMADA COPIAS DE SEGURIDAD MANUAL DE AYUDA TAREA PROGRAMADA COPIAS DE SEGURIDAD Fecha última revisión: Diciembre 2010 Tareas Programadas TAREAS PROGRAMADAS... 3 LAS TAREAS PROGRAMADAS EN GOTELGEST.NET... 4 A) DAR DE ALTA UN USUARIO...

Más detalles

MANUAL DE USUARIO Y EJEMPLO DE UTILIZACIÓN HERRAMIENTA DLP-DELPHI LEARNING PACKAGE

MANUAL DE USUARIO Y EJEMPLO DE UTILIZACIÓN HERRAMIENTA DLP-DELPHI LEARNING PACKAGE MANUAL DE USUARIO Y EJEMPLO DE UTILIZACIÓN HERRAMIENTA DLP-DELPHI LEARNING PACKAGE PROFESOR: Creación y puesta en marcha de un proceso de aprendizaje Delphi: En esta fase el profesor debe realizar las

Más detalles

NOTAS TÉCNICAS SOBRE EL SIT: Documentos de Gestión

NOTAS TÉCNICAS SOBRE EL SIT: Documentos de Gestión NOTAS TÉCNICAS SOBRE EL SIT: Documentos de Gestión Introducción...2 Tipos de documentos...2 Datos de Cabecera...3 Nuevo Documento... 3 Modificar Documento... 4 Añadir, modificar y eliminar Artículos...5

Más detalles

GedicoPDA: software de preventa

GedicoPDA: software de preventa GedicoPDA: software de preventa GedicoPDA es un sistema integrado para la toma de pedidos de preventa y gestión de cobros diseñado para trabajar con ruteros de clientes. La aplicación PDA está perfectamente

Más detalles

Análisis de los datos

Análisis de los datos Universidad Complutense de Madrid CURSOS DE FORMACIÓN EN INFORMÁTICA Análisis de los datos Hojas de cálculo Tema 6 Análisis de los datos Una de las capacidades más interesantes de Excel es la actualización

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