AÑO DE LAS CUMBRES MUNDIALES EN EL PERU" ESCUELA DE INGENIERIA DE SISTEMAS UCV – PIURA
INTEGRANTES : • • • • DOCENTE :
CURSO
Huanca Cruz Joan Eddy Mendoza Yovera Lucia Carolina Balcazar Rivas Renato Hernández Abramonte Wilfredo
• Ing. CIP Aldo Pereda Castillo : • Programación Orientada a Objetos
CICLO
:
ESCUELA
:
• IV
• Ing. Sistemas
2008 1
INTRODUCCION El tema que trataremos en el presente trabajo, es uno de los más interesantes que puede tener un lenguaje de programación (java), muchos al iniciarnos en este muy bonito e interesante mundo de la programación, solo realizábamos programas (c, c++, etc.), el cual trataba de darle una orden y este cumpliese con un cometido, no dándonos la oportunidad de realizar otra cosa si es que por ejemplo: esperaba que ingrese algún dato. Este problema es superado con java, que nos brinda la oportunidad de realizar distintas acciones, en tiempo compartido, es decir dar la sensación de realizar infinidad de cosas al mismo tiempo, pero que en realidad internamente es un simple repartimiento de memoria. Todos tenemos siempre aunque en forma indirecta el contacto con este mecanismo: cuando hacemos el uso del programa Microsoft Word vemos que este programa realiza tareas de forma “Simultanea”, por ejemplo, podemos estar escribiendo y a la vez el programa está revisando los errores ortográficos para corregirlos. O también el mismo sistema operativo por que puede estar copiando archivos, a la vez mostrando la hora, navegando por internet, etc. Sin más preámbulos empecemos con todo lo que concierne a los Threads, un tema que a mi parecer es la matriz de la programación orientada a objetos.
2
INDICE
III.
QUE ES UNTHREAD……………………………………………………………………………………… 3 ¿PARA QUE SE UTILIZAN ? 1. TIPOS DE THREAD 2. CONTROL BASICO DE UN THREAD CLASES RELACIONADAS CON LOS HILOS……………………………………………5 1. LA CLASE THREADS 2. Runnable 3. ThreadDeath 4. TreadGroup 5. Object CICLO DE VIDA DE UN THREAD ………………………………………………………………8
IV.
PRIORIDADES ……………………………………………………………………………………………….8
I.
II.
CONTROL DE UN HILO………………………………………………………………………………..12 1. Arranque de un hilo 2. Manipulación de un hilo 3. Suspensión de un Hilo 4. Parada de un Hilo • stop () • isAlive () VI. AGRUPAMIENTO DE HILOS……………………………………………………………………...13 1. Grupo de hilos por defecto 2. Grupo de hilos de forma explicita VII. LA CLASE ThreadGroup …………………………………………………………………………………15
V.
VIII.
THREAD DAEMON………………………………………………………………………………………….15
IX . SINCRONIZACION……………………………………………………………………………………………..16 1. Uso de synchronized. 2. Comunicación entre threads 3. Monitores IX. CONCLUSIONES………………………………………………………………………………………………….18
3
I. QUE ES UN THREAD: También conocido en java como hilos o subproceso. Los threads o hilos de ejecución son segmentos de código de un programa que se ejecutan secuencialmente de modo independiente de otras partes del programa.Un proceso puede estar constituido por uno o mas threads. Un thread es un contexto de ejecución, proceso ligero o tarea donde hay un flujo secuencial de control y que utiliza los recursos disponibles para un programa. 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 detalles, asignación de tiempos de ejecución, prioridades, etc. De forma similar a como gestiona un Sistema Operativo múltiples procesos. La diferencia básica entre un proceso de Sistema Operativo y un Thread Java es que los hilos corren dentro de la JVM, que es un proceso del Sistema Operativo y por tanto comparten todos los recursos, incluida la memoria y las variables y objetos allí definidos. A este tipo de procesos donde se comparte los recursos se les llama a veces procesos ligeros. Desde el punto de vista de las aplicaciones los hilos son útiles porque permiten que el flujo del programa sea divido en dos o más partes, cada una ocupándose de alguna tarea de forma independiente. Por ejemplo un hilo puede encargarse de la comunicación con el usuario, mientras que otros actúan en segundo plano, realizando la transmisión de un fichero, Accediendo a recursos del sistema (cargar sonidos, leer ficheros...), etc. De hecho, todos los programas con interfaz gráfico (AWT o Swing) son multihilo porque los eventos y las rutinas de dibujado de las ventanas corren en un hilo distinto al principal. ¿PARA QUE SE UTILIZAN ? Los threads se utilizan para aislar y coordinar tareas. Sin el uso de threads hay aplicaciones que son casi imposibles de programar: • Las que tienen tiempos de espera importantes entre etapas • Las que consumen muchos recursos de CPU e impiden que el procesador atienda simultáneamente otros eventos o peticiones del usuario
4
1. TIPOS DE THREAD Tipos de threads que pueden aparecer en una aplicación:
•
Threads completamente independientes, que realizan tareas no relacionadas. Éste es el caso más sencillo y no requiere ninguna programación especial.
•
Threads que trabajan en una misma tarea, pero sin interferir ni intercambiar relación entre ellos. Por ejemplo, threads que colaboran en el producto de dos matrices ocupándose cada una de ellas de calcular ciertas filas de la matriz producto.
•
Threads que utilizan recursos de modo mutuamente exclusivo, aunque sin tener que coordinar sus actividades. Por ejemplo, threads que actualizan o leen registros de una base de datos y que no pueden actuar simultáneamente.
•
Threads que deben de coordinar sus actividades, de modo que una de ellas no puede empezar o continuar hasta que la otra haya realizado su tarea. Los ejemplos más típicos son los de tipo productorconsumidor, en el que este último tiene que esperar para realizar su función a que el productor le haya preparado los datos y le avise de esa circunstancia.
2. CONTROL BASICO DE UN THREAD •
Finalización del la ejecución de un thread.
o Cuando un thread acaba su ejecución y es finalizado, no puede volver a ser ejecutado. o Podemos detener un thread utilizando un flag que utiliza un método run que debe terminar la ejecución. • r.stopRunning() // r instancia de una clase que implementa runnable •
Verificación del estado thread isAlived() o boolean isAlived (). Devuelve true si el thread ha sido inicializado con start y no ha terminado el ciclo de ejecución. • Bloqueo de threads. o sleep(). Permite detener un thread durante un determinado tiempo
5
o join(). Bloquea el thread actual, hasta que el thead sobre el cual ha sido ejecutado el join termina.
II. CLASES RELACIONADAS CON LOS HILOS: El lenguaje de programación Java proporciona soporte para hilos a través de una simple interfase. Y un conjunto de clases. La interfase de Java y las clases que incluyen funcionalidades sobre Hilos son las siguientes: • • • • •
Thread Runnable ThreadDeath ThreadGroup Object
Todas estas clases son parte del paquete Java.lang.
1. la clase thread La clase Thread es la clase responsable de producir hilos funcionales para otras clases. La forma más directa para añadir la funcionalidad a un hilo es extender la clase Thread, y redefinir el método run (). Este método es invocado cuando se inicia el hilo (mediante una llamada a método start () de la clase Thread). El hilo se inicia con la llamada al método run () y termina cuando termina éste. Pero esta forma nos provoca algunas limitaciones, como bien sabemos JAVA no admite la herencia múltiple, Así que si queremos heredar de otra clase ya no lo podemos hacer por que ya estamos heredando de la clase thread; pero felizmente existe una solución a este inconveniente, esto se realiza implementando lo que llamamos como interfaz, debemos implementar la interfaz runnable que veremos más a delante. El ejemplo ilustra estas ideas:
public class ThreadEjemplo extends Thread { public ThreadEjemplo (String str) { super (str); }
6
public void run() { for (int i = 0; i < 10 ; i++) System.out.println (i + " " + getName ()); System.out.println ("Termina thread” + getName ()); } Public static void main (String [] args) { new ThreadEjemplo ("Pepe").start(); new ThreadEjemplo("Juan").start(); System.out.println("Termina thread main"); } }
2. Runnable Java no soporta herencia múltiple de forma directa, es decir, no se puede derivar una clase de varias clases padre. Esto nos plantea la duda sobre cómo podemos añadir la funcionalidad de Hilo a una clase que deriva de otra clase, siendo ésta distinta de Thread. Para lograr esto se utiliza la interfaz Runnable. La interfaz Runnable proporciona la capacidad de añadir la funcionalidad de un hilo a una clase simplemente implementando la interfaz, en lugar de derivándola de la clase Thread. Las clases que implementan la interfaz Runnable proporcionan un método run que es ejecutado por un objeto hilo asociado que es creado aparte. Esta es una herramienta muy útil y a menudo es la única salida que tenemos para incorporar multihilo dentro de las clases. Esta cuestión será tratada más ampliamente en el apartado de Creación de hilos. Aunque es un único método el que se define en esta interfaz
3. ThreadDeath La clase de error ThreadDeath proporciona un mecanismo que permite hacer limpieza después de que un hilo haya sido finalizado de forma asíncrona. Se llama a ThreadDeath una clase error porque deriva de la clase Error, la cual proporciona medios para manejar y notificar errores. Cuando el método stop de un hilo es invocado, una instancia de ThreadDeath es lanzada por el moribundo hilo como un error. Sólo se debe recoger el objeto ThreadDeath si se necesita para realiza una limpieza específica a la terminación asíncrona, lo cual es una
7
situación bastante inusual. Si se recoge el objeto, debe ser relanzado para que el hilo realmente muera.
4. ThreadGroup La clase ThreadGroup se utiliza para manejar un grupo de hilos de modo conjunto. Esto nos proporciona un medio para controlar de modo eficiente la ejecución de una serie de hilos. Por ejemplo la clase ThreadGroup nos proporciona métodos stop, suspend y resume para controlar la ejecución de todos los hilos pertenecientes al grupo. Los grupos de hilos también Pueden contener otros grupos de hilos permitiendo una jerarquía anidada de hilos. Los hilos individuales tienen acceso al grupo pero no al padre del grupo.
5. Object Aunque, estrictamente hablando, no es una clase de apoyo a los hilos, la clase objeto proporciona unos cuantos métodos cruciales dentro de la arquitectura multihilo de Java. Estos métodos son wait, notify y notifyAll. El método wait hace que el hilo de ejecución espere en estado dormido hasta que se le notifique que continúe. Del mismo modo, el método notify informa a un hilo en espera de que continúe con su ejecución. El método notifyAll es similar a notify excepto que se aplica a todos los hilos en espera. Estos tres métodos solo pueden ser llamados desde un método o bloque sincronizado (o bloque de sincronización). Normalmente estos métodos se utilizan cuando hay ejecución multihilo, es decir, cuando un método espera a que otro método termine de hacer algo antes de poder continuar. El primer hilo espera hasta que otro hilo le notifique que puede continuar. La clase objeto está en la parte superior de la jerarquía de Java, lo cual significa que es el padre de todas las clases. En otras palabras, cada clase Java hereda la funcionalidad proporcionada por la clase objeto, incluyendo los métodos wait, notify y notifyAll.
8
III. CICLO DE VIDA DE UN THREAD:
El inicio de este ciclo empieza con la instancia de la clase thread, es decir se crea un nuevo thread que está en su estado inicial; en este estado es solo un objeto más. No existe el thread en ejecución. El único método que puede invocarse sobre él es el método Start(). Al invocarse éste sobre el hilo el sistema crea los recursos necesarios, lo planifica (le asigna prioridad) y luego llama al método run(). En este momento el hilo está corriendo se encuentra en estado runnable (ejecutable). Si el método run() invoca internamente el método sleep() o wait() o el hilo tiene que esperar por una operación de entrada/salida, entonces el hilo pasa al estado no runnable (no ejecutable) hasta que la condición de espera finalice. Durante este tiempo el sistema puede ceder control a otros hilos activos. Por último cuando el método run finaliza el hilo termina y pasa a la situación Dead (Muerto).
IV.PRIORIDADES: Los programas en java pueden utilizar el subprocesamiento múltiple. Todo subproceso o hilo en java tiene una prioridad en el rango entre Thread. MIN_PRIORITY (una constante de 1) y Thread.MAX_PRIORITY (una constante de 10). De manera informal, los hilos con mayor prioridad son mas importantes para un programa, y se les debe asignar tiempo en el procesador antes que a los hilos de menor prioridad. Sin embargo las prioridades de los
9
hilos no pueden garantizar el orden en que se ejecutarán. De manera predeterminada, a cada hilo se le asigna la prioridad Thread.NORM_PRIORITY (una constante de 5). Cuando hay varios hilos en condiciones de ser ejecutados (estado runnable), la máquina virtual elige el hilo que tiene una prioridad más alta, que se ejecutará hasta que:
•
Un hilo con una prioridad más alta esté en condiciones de ser ejecutado (runnable)
•
El hilo termina (termina su método run)
•
Se detiene voluntariamente
•
Alguna condición hace que el hilo no sea ejecutable (runnable), como una operación de entrada/salida o, si el sistema operativo tiene planificación por división de tiempos (time slicing), cuando expira el tiempo asignado.
Si dos o más hilos están listos para ejecutarse y tienen la misma prioridad, la máquina virtual va cediendo control de forma cíclica (round-robin). El hecho de que un hilo con una prioridad más alta interrumpa a otro se denomina se denomina planificación apropiativa (preemptive scheduling). Cuando un hilo entra en ejecución y no cede voluntariamente el control para que puedan ejecutarse otros hilos, se dice que es un hilo egoísta (selfish thread). Algunos Sistemas Operativos, como Windows, combaten estas actitudes con una estrategia de planificación por división de tiempos (time-slicing), que opera con hilos de igual prioridad que compiten por la Sistemas Distribuidos. En estas condiciones el Sistema Operativo asigna tiempos a cada hilo y va cediendo el control consecutivamente a todos los que compiten por el control de la CPU, impidiendo que uno de ellos se apropie del sistema durante un intervalo de tiempo prolongado. Recordar que este mecanismo lo da el sistema operativo, no JAVA.
Métodos para el manejo de prioridades:
10
•
SetPriority; Ajusta la prioridad de un hilo o thread, el cual acepta un argumento int en el rango de 1-10.
•
GetPriority; Devuelve la prioridad del subproceso o hilo.
•
Yield; da a otros subprocesos o hilos la oportunidad para ejecutarse.
OTRA FORMA DE CREAR HILOS Implementándolo con la interfase Runnable. Veamos el siguiente ejemplo: public class MiThread implements Runnable { Thread t; public void run() { // Ejecución del thread una vez creado } } En este caso necesitamos crear una instancia de Thread antes de que el sistema pueda ejecutar el proceso como un hilo. Además, el método abstracto run que está definido en la interfaz Runnable tiene que implementarse en la nueva clase creada. La diferencia entre ambos métodos de creación de hilos en Java radica en la flexibilidad con que cuenta el programador, que es mayor en el caso de la utilización de la interfaz Runnable. Sobre la base del ejemplo anterior, se podría extender la clase MiThread a continuación, si fuese necesario. La mayoría de las clases creadas que necesiten ejecutarse como un hilo implementarán la interfaz Runnable, ya que así queda cubierta la posibilidad de que sean extendidas por otras clases. Por otro lado, es un error pensar que la interfaz Runnable está realizando alguna tarea mientras un hilo de alguna clase que la implemente se está ejecutando. Es una interfaz, y como tal, sólo contiene funciones abstractas (concretamente una única, run), proporcionando tan solo una idea de diseño, de infraestructura, de la clase Thread, pero ninguna funcionalidad. Su declaración en Java tiene el siguiente aspecto:
package Java.lang;
11
public interfaz Runnable { public abstract void run() ; } Comentados los aspectos más importantes de la interfaz Runnable, veamos ahora la definición de la clase Thread, de la cual podemos deducir lo que realmente se está haciendo: public class Thread implements Runnable { ... public void run() { if( tarea != null ) tarea.run () ; } ...} Se deduce, por tanto, que la propia clase Thread de Java también implementa la interfaz Runnable. Observamos que en el método run de Thread se comprueba si la clase con que se está trabajando en ese momento (tarea), que es la clase que se pretende ejecutar como hilo, es o no nula. En caso de no ser nula, se invoca al método run propio de dicha clase. Una vez de haber visto las dos maneras de crear un hilo , sale a la luz la interrogante de cual es mejor usar , a continuación veamos un poco de los beneficios de cada uno :
o Implementar la interfaz Runnable: • Mejor diseño orientado a objetos. La clase thread solo deberá ser extendida cuando se pretenda modificar o extender el comportamiento de dicho modelo de ejecución. • Herencia simple. Debido a la tecnología de Java no es posible extender una clase cuando ésta ya ha sido extendida a la clase thread
o Extender la clase Thread: • Código más simple. En el método run la referencia this apunta a la instancia del thread actual
V. CONTROL DE UN HILO: 12
1. Arranque de un hilo En el contexto de las aplicaciones, sabemos que es main la primera función que se invoca tras arrancar, y por tanto, lógicamente, es el lugar más apropiado para crear y arrancar otros hilos. La línea de código: TestTh t1 = new TestTh (“Thread 1",(int) (Math.random ()*2000)); siendo TestTh una subclase de la clase Thread (o una clase que implemente la interfaz Runnable) crea un nuevo hilo. Los dos argumentos pasados, sin mayor relevancia, satisfarán el prototipo del constructor de la clase y se utilizarán para la inicialización del objeto. Al tener control directo sobre los hilos, tenemos que arrancarlos explícitamente. Como ya se comentó anteriormente, es la función miembro start la que nos permite hacerlo. En nuestro ejemplo sería: start (); en realidad es un método oculto en el hilo que llama al método run.
2. Manipulación de un hilo Si todo fue bien en la creación del objeto TestTh (t1), éste debería contener un hilo, una traza de ejecución válida, que controlaremos en el método run del objeto. El cuerpo de esta función miembro viene a ser el cuerpo de un programa como ya los conocemos. Digamos que es la rutina main a nivel de hilo. Todo lo que queremos que haga el hilo debe estar dentro del método run. Cuando finalice run, finalizará también el hilo que lo ejecutaba. 3. Suspensión de un Hilo La función miembro suspend de la clase Thread permite tener un control sobre el hilo de modo que podamos desactivarlo, detener su actividad durante un intervalo de tiempo indeterminado, a diferencia del uso de la llamada al sistema sleep, que simplemente lleva al hilo a un estado de “dormido”, y siempre durante un número de milisegundos concreto. Este método puede resultar útil si, construyendo un applet con un hilo de animación, queremos permitir al usuario detener (que no finalizar) la animación, hasta que éste decida reanudarla.
13
El hilo es suspendido indefinidamente y para volver a activarlo de nuevo necesitamos realizar una invocación a la función miembro resume.
4. Parada de un Hilo Ya conocemos los métodos de control de hilos que nos permiten arrancarlos, suspenderlos y reanudarlos. El último elemento de control que se necesita sobre hilos es el método stop, utilizado para terminar la ejecución de un hilo de forma permanente:
•
stop ();
Señalar que esta llamada no destruye el hilo, sino que detiene su ejecución, y ésta no puede reanudarse con el método start. Cuando se designen las variables que se usan en el hilo, el objeto hilo (creado con new) quedará marcado para eliminarlo y el garbage collector (recolector de basura de Java) se encargará de liberar la memoria que utilizaba. Tiene sentido su utilidad, por ejemplo, en aplicaciones complejas que necesiten un control sobre cada uno de los hilos que se lancen. Por último, un método de control de hilos que nos permite comprobar si una instancia está viva (el hilo se ha arrancado y aún no se ha detenido) o no (bien no se arrancó; bien ya finalizó). Estamos hablando de la función miembro isAlive.
•
isAlive ();
Devolverá true en caso de que el hilo esté vivo, es decir, ya se haya llamado a su método run y no haya sido parado con un stop ni haya terminado el método run en su ejecución. En otro caso, lógicamente, devolverá false.
VI. AGRUPAMIENTO DE HILOS: Todo hilo de Java es un miembro de un grupo de hilos. Los grupos de hilos proporcionan un mecanismo de reunión de múltiples hilos dentro de un único objeto y de manipulación de dichos hilos en conjunto, en lugar de una forma individual. Por ejemplo, se pueden arrancar o suspender todos los hilos que están dentro de un grupo con una única llamada al método. Los grupos de hilos de Java están implementados por la clase ThreadGroup en el paquete Java.lang.
14
El runtime system (sistema de tiempo de ejecución) de Java pone un hilo dentro de un grupo de hilos en el momento de la construcción del mismo. Cuando creas un hilo, se puede dejar que el sistema de tiempo de ejecución ponga el nuevo hilo en algún grupo razonable por defecto, o se puede establecer explícitamente el grupo del nuevo hilo. El hilo es un miembro permanente de aquel que sea el grupo de hilos al cual se unió en el momento de su creación. No puede moverse un hilo a un nuevo grupo una vez que ha sido creado.
1.Grupo de hilos por defecto Si se crea un nuevo hilo sin especificar su grupo en el constructor, el sistema de tiempo de ejecución colocará el nuevo hilo automáticamente en el mismo grupo que el hilo que lo ha creado (conocido como grupo de hilos actual e hilo actual, respectivamente). Así que, ¿cuál es el grupo de hilos del hilo principal de una aplicación? Cuando se arranca una aplicación Java, el sistema de tiempo de ejecución de Java crea una instancia de la clase ThreadGroup llamada main. A menos que especifiques lo contrario, Todos los nuevos hilos que crees se convertirán en miembros del grupo de hilos main.
2.Grupo de hilos de forma explicita Como hemos mencionado anteriormente, un hilo es un miembro permanente de aquel grupo de hilos al cual se unió en el momento de su creación (no tenemos la posibilidad de cambiarlo posteriormente). De este modo, si quieres poner tu nuevo hilo en un grupo de hilos distinto del grupo por defecto, debes especificarlo explícitamente cuando lo creas. La clase Thread tiene tres constructores que te permiten establecer un nuevo grupo de hilos: • public Thread( ThreadGroup group, Runnable runnable ) • public Thread( ThreadGroup group, String name ) • public Thread( ThreadGroup group, Runnable runnable, String name ) Cada uno de estos constructores crea un nuevo hilo, lo inicializa en base a los parámetros Runnable y String, y hace al nuevo hilo miembro del grupo especificado. Por ejemplo, la siguiente muestra de código crea un grupo de hilos (myThreadGroup) y entonces crea un hilo (myThread) en dicho grupo ThreadGroup myThreadGroup = new ThreadGroup( “My Group of Threads” ); Thread myThread = new Thread( myThreadGroup, “a thread for my group” );
15
El ThreadGroup pasado al constructor Thread no tiene que ser necesariamente un grupo que hayas creado tú, puede tratarse de un grupo creado por el sistema de ejecución de Java, o un grupo creado por la aplicación en la cual se está ejecutando el applet. Como ya hemos visto anteriormente un concepto sobre la clase ThreadGroup, ahora lo profundizaremos más.
VII. LA CLASE ThreadGroup: La clase ThreadGroup es la implementación del concepto de grupo de hilos en Java. Ofrece, por tanto, la funcionalidad necesaria para la manipulación de grupos de hilos para las aplicaciones Java. Un objeto ThreadGroup puede contener cualquier número de hilos. Los hilos de un mismo grupo generalmente se relacionan de algún modo, ya sea por quién los creó, por la función que llevan a cabo, o por el momento en que deberían arrancarse y parar. El grupo de hilos de más alto nivel en una aplicación Java es el grupo de hilos denominado main. • getMaxPriority y setMaxPriority • getDaemon y SetDaemon • getName • getParent y parentOf • toString • resume • stop • suspend
IX.
THREAD DAEMON:
Los threads daemon llamados servicios, se ejecutan con prioridad baja y proporcionan un servicio básico a un programa o programas cuando la actividad de la máquina es reducida.
a. Un ejemplo de thread demonio que está ejecutándose continuamente es el recolector de basura (garbage collector). E b. Un thread puede fijar su indicador de demonio pasando un valor true al método setDaemon(). Si se pasa false a este método, el thread será devuelto por el sistema como un thread de usuario. No obstante, esto último debe realizarse antes de que se arranque el thread (start ()).
16
VIII. SINCRONIZACION: o Existen muchas situaciones interesantes donde ejecutar threads concurrentes que compartan datos y deban considerar el estado y actividad de otros threads. Este conjunto de situaciones de programación son conocidos como escenarios 'productor/consumidor'; donde el productor genera un canal de datos que es consumido por el consumidor. Como los threads comparten un recurso común, deben sincronizarse de alguna forma.
1. Uso de synchronized. o Cada objeto tiene un “flag de bloqueo” La palabra clave synchronized permite controlar el flag para activar accesos exclusivos al objeto y cada objeto tendrá asociada una cola de espera. •
Se pueden declarar bloques de código synchronized. synchronized ( variableCompartida ) {
// acceso al recurso
} •
Métodos synchronized public synchronized void nomMetode () {
// acceso al recurso
} o El flag de bloqueo de un objeto se libera : – Cuando el thread termina el bloque de código synchronized – Cuando le bloque de código synchronized lanza una excepción. o Deadlock – Dos threads esperando un flag de bloqueo – No se detecta – Se puede evitar: • Decidir el orden de obtención de los bloqueos • Seguir con rigurosidad ese orden • Liberar los bloqueos en orden inverso
17
2. Comunicación entre threads o wait() y notify() • Si un thread ejecuta una llamada wait() sobre un objeto x pausará su ejecución hasta que otro thread ejecute la llamada a notify() mediante el mismo objeto x. • Para poder ejecutar tanto un wait() como un notify() el thread deberá disponer del flag de bloqueo, es decir, solo podrán ser ejecutadis desde un bloque de código synchronized. • Listas de espera o “pools” - Cuando un thread ejecuta wait() se libera el flag de bloqueo y es colocado en la lista de espera o pool del objeto (wait pool) -Al ejecutar notify() un thread arbitrario es movido de la lista de espera hacia una lista de threads que esperan por el flag de bloqueo (lock pool). notifyAll() despierta a todos los threads.
3. Monitores o Cuando un método synchronized se ejecuta adquiere un monitor sobre el objeto. Cuando un thread tiene el monitor del objeto ningún otro thread podrá ejecutar un método synchronized. o Un thread sale del monitor cuando libera el flag de bloqueo del objeto. o Un ejemplo típico del uso de monitores es el esquema de productor/consumidor. o Aquí el productor y el consumidor son threads que acceden a la región critica que es la tubería o buffer. Esta tiene que tener sus métodos protegidos mediante synchronized y tiene que hacer que los threads se comuniquen mediante wait(), notify() y notifyAll().
18
IX. CONCLUSIONES: • • •
• • • • •
• •
•
•
• •
•
java, que nos brinda la oportunidad de realizar distintas acciones, en tiempo compartido, También conocido en java como hilos o subprocesos Un thread es un contexto de ejecución, proceso ligero o tarea donde hay un flujo secuencial de control y que utiliza los recursos disponibles para un programa. La Máquina Virtual Java (JVM) es un sistema multihilo. La diferencia básica entre un proceso de Sistema Operativo y un Thread Java es que los hilos corren dentro de la JVM. A este tipo de procesos donde se comparte los recursos se les llama a veces procesos ligeros. Desde el punto de vista de las aplicaciones los hilos son útiles porque permiten que el flujo del programa sea divido en dos o más partes, La clase Thread es la clase responsable de producir hilos funcionales para otras clases. provoca algunas limitaciones, como bien sabemos JAVA no admite la herencia múltiple, para ello, debemos implementar la interfaz runnable. Para lograr añadir la funcionalidad de Hilo a una clase que deriva de otra clase, siendo ésta distinta de Thread se utiliza la interfaz Runnable. Las clases que implementan la interfaz Runnable proporcionan un método run que es ejecutado por un objeto hilo asociado que es creado aparte. La clase de error ThreadDeath proporciona un mecanismo que permite hacer limpieza después de que un hilo haya sido finalizado de forma asíncrona deriva de la clase Error. La clase ThreadGroup se utiliza para manejar un grupo de hilos de modo conjunto El método wait hace que el hilo de ejecución espere en estado dormido hasta que se le notifique que continúe. Del mismo modo, el método notify informa a un hilo en espera de que continúe con su ejecución. El método notifyAll es similar a notify excepto que se aplica a todos los hilos en espera. Todo subproceso o hilo en java tiene una prioridad en el rango entre Thread.MIN_PRIORITY (una constante de 1) y Thread.MAX_PRIORITY (una constante de 10).
19