|
| Knowledge Base |
|
|
|
| Inicio >
Java > Threads |
|
|
Threads
|
| Qué es un thread y cómo funciona |  |
|
Un thread de Java es un contexto de ejecución o un proceso ligero. Es un solo
flujo secuencial de control dentro de un programa. El programador puede utilizar
el mecanismo del thread de Java para ejecutar múltiples tareas simultáneamente.
| |
| La clase Thread y el método run() |
- La ayuda básica para los threads está en la clase java.lang.Thread.
Proporciona un API de threads y todo su comportamiento genérico. Estos
comportamientos incluyen arrancar, suspender, el funcionamiento, el rendimiento,
y la obtención de prioridad.
- El método run() proporciona al thread algo para hacer. Su código debe poner
en funcionamiento el thread.
Hay dos formas de crear un thread personalizado:
- Creando subclases java.lang.Thread y sobreescribiendo el método run().
- Implementando la interfaz java.lang.Runnable.
|
| |
- Cuando decimos que los threads están funcionando concurrentemente, en la práctica
puede que no sea así. En un ordenador con una sola CPU, los threads funcionan realmente
uno a la vez dando una ilusión de la concurrencia.
- La ejecución de múltiples threads en una sola CPU basada en un cierto algoritmo
se llama thread scheduling.
- Los thread scheduler mantienen una reserva de todos los threads preparados para
arrancar.De acuerdo con el algoritmo fijo de prioridad, asigna la CPU libre a uno
de estos threads.
|
| |
| Ciclo de vida de un Thread |
El diagrama siguiente ilustra los varios estados que un thread puede tener durante el
transcurso de su vida y las llamadas de los método que causan la transición a otro estado.
Ready-to-run
Un thread comienza su ciclo vida con una llamada al método start(). Por ejemplo:
MyThread aThread = new MyThread();
aThread.start();
Una llamada start() no provocará la ejecución inmediatamente del thread, sino
la moverá a la reserva de threads, esperando su turno para ser escogido para
la ejecución.El thread scheduling escoge uno de los thread preparados para
arrancar de acuerdo con las prioridades del thread.
Running
El código del thread está siendo ejecutado activamente por el procesador.
Funciona hasta que se intercambia, se bloquea, o cede voluntariamente su
turno con este método estático
Thread.yield();
Observe que el yield() es un método estático. Incluso si es llamado en algún
objeto del thread, provoca que la ejecución actual del thread ceda la CPU.
Waiting
Una llamada al método wait() de java.lang.Object provoca que el objeto actual
del thread espere. El thread permanece en estado "waiting" hasta que algún otro
thread invoque el notify() o el método del notifyAll() de este objeto. El thread
actual debe poseer el monitor de este objeto para llamar al wait().
Sleeping
El Java thread se puede forzar a dormir(suspendido) durante un tiempo
predefinido
Thread.sleep(milisegundos);
Thread.sleep(milisegundos, nanosegundos);
Observe que el metodo estático sleep() solo garantiza que el thread dormirá por
un tiempo predefinido y que funcionará un cierto rato después que haya
transcurrido dicho tiempo.
Por ejemplo, una llamada a sleep(60) provocará que la actual ejecución del thread
duerma 60 milisegundos. Este thread estará en estado "ready-to-run" después de
este tiempo. Estará en estado de "funcionamiento" solamente cuando el planificador lo
escoja para la ejecución. Así podemos decir que el thread funcionará de nuevo
después de los 60 milisegundos.
Blocked on I/O
Un thread de java puede incorporar este estado mientras espera datos del
dispositivo del I/O. El thread se moverá a Ready-to-run(Listo-para-correr) después
de que la condición de I/O cambie(por ejemplo la lectura de un octeto de datos).
Blocked on Synchronization
Un thread de java puede incorporar este estado mientras espera el bloqueo del
objeto. El thread se moverá a Ready-to-run cuando se adquiera el bloqueo.
Dead
Un thread de java puede incorporar este estado cuando ha finalizado el trabajo.
Puede también incorporar este estado si el thread es finalizado por un error
irrecuperable.
|
| |
| Sincronización del Thread |
Los problemas pueden ocurrir cuando dos threads están intentando acceder/modificar el mismo
objeto. Para prevenir estos problemas, java utiliza monitores y la clave sincronizada para
controlar el acceso a un objeto por el thread.
Monitor
- Monitor es cualquier clase con código sincronizado en ella.
- Monitor controla sus threads clientes usando los métodos wait() y notify() (o notifyAll()).
- Los métodos del wait() y del notify() tienen que ser llamados en código sincronizado.
- El monitor pide al thread del cliente esperar si no está disponible.
- Normalmente una llamada al wait() es situada en un bucle. La condición del
bucle prueba generalmente la disponibilidad del monitor. Después de esperar,
el thread reanuda la ejecución desde el punto donde lo dejó.
Código sincronizado y bloqueos
-
Objeto bloqueo
Cada objeto tiene un bloqueo. El bloqueo puede ser controlado por mas de un thread a
la vez. Bloquea los controles de acceso al código sincronizado.
- Cuando un thread al ejecutarse encuentra una declaración sincronizada, entra en
estado bloqueado y espera hasta que adquiere el bloqueo del objeto. Después,
ejecuta el bloque del código y libera el bloqueo. Mientras la ejecución de
un thread posea el bloqueo, ningún otro thread podrá adquirir el bloqueo.
Así los bloqueos y el mecanismo de la sincronización asegura la excepción apropiado
del código en múltiple threading.
|
| |
Una prioridad del thread se especifica con un número entero desde 1 (el más bajo) a
10 (el más alto), las constantes Thread.MIN_PRIORITY y Thread.MAX_PRIORITY pueden también
ser utilizadas. Por defecto, el método del setPriority() fija la prioridad del thread a 5,
que es el Thread.NORM_PRIORITY.
Thread aThread = Thread.currentThread();
int currentPriority;
currentPriority = aThread.getPriority();
aThread.setPriority( currentPriority + 1 );
Fijar prioridades puede siempre no tener el efecto deseado porque los esquemas
de la priorización pueden ser implementadas de forma diferente o en distintas plataformas.
Sin embargo, utilice prioridades más altas para los threads que bloquean con frecuencia
(para I/O sleeping o waiting). Cambie la intensidad de la CPU de media a baja para evitar
la caída del procesador.
|
| |
En múltiple threading, pueden ocurrir los siguientes problemas:
- El deadlock o abrazada mortal ocurre cuando dos o más threads están intentando
conseguir el control del mismo objeto, y cada uno tiene un bloqueo en otro recurso que
ellos necesitan para continuar.
- Por ejemplo, cuando el thread A está esperando para bloquear un objeto P mientras
tiene bloqueado un Objeto Q y al mismo tiempo, el thread B tiene bloqueado un Objeto P
y está esperando para bloquear un objeto Q, en ese momento ocurre un deadlock.
- Observe que si el thread está llevando a cabo un bloqueo y va a un estado sleeping,
no suelta el bloqueo. Sin embargo, cuando el thread entra en estado bloqueado,
deja normalmente el bloqueo. Esto elimina potencialmente los deadlocks de los threads.
- Java no proporciona ninguna mecanismos para la detección o el control de las
situaciones de los deadlocks, así que el programador es responsable de evitarlos.
|
Copyright © 1998-2008 DEISTER, S.A. - Todos los derechos reservados. Modificado: 5-mayo-2011
|