Cómo implementar la cola de mensajes en Java
La cola de mensajes es un método de comunicación entre subprocesos:
import?java.util.*
public?class?MsgQueue {
¿privado?Vector?queue?=?null;
público?MsgQueue(){ cola?=?newVector();
}
¿público?sincronizado?void?send(Objeto?o)
{ queue.addElement(o);
}
¿público?sincronizado?Objeto?recv( )
{ if(queue.size()==0)
return?o;
}
}
Dado que Java está bloqueado a través de objetos, agregar sincronizado se puede usar para bloquear objetos de sincronización de subprocesos
Se puede usar como una cola para almacenar tareas para el procesamiento de subprocesos múltiples.
Se puede utilizar como una cola multiproceso y multitarea para almacenar tareas. Su cliente incluye clases de tareas encapsuladas y clases de subprocesos
Múltiples subprocesos en Java: comunicación entre subprocesos 2009-08-25?21:58
1 Estado de varios tipos de subprocesos
Los subprocesos tienen cuatro estados y cualquier subproceso debe estar en uno de estos cuatro estados:
1)?Generado (nuevo): el objeto del subproceso se ha generado pero aún no se ha iniciado. por lo que no se puede ejecutar. Por ejemplo, después de generar un objeto de hilo a través de new, la función start() no se ha llamado antes.
2) Ejecutable: cada sistema que admite subprocesos múltiples tiene un programador que selecciona un subproceso del grupo de subprocesos y lo inicia. Cuando un subproceso está en estado ejecutable, es posible que esté esperando en el grupo de subprocesos a que se inicie el programador y es posible que ya se esté ejecutando. Si ejecuta el método start() del objeto hilo, el hilo estará en un estado ejecutable, pero obviamente el hilo no necesariamente se está ejecutando.
3) Muerte: Cuando un hilo termina normalmente, muere. Por ejemplo, después de que la función thread run() completa la ejecución, el hilo entra en estado muerto.
4) Bloqueo: Cuando un hilo está bloqueado, el programador del sistema lo ignorará y no lo programará. Cuando un subproceso estancado vuelve a un estado ejecutable, es posible que se vuelva a ejecutar. Por ejemplo, al llamar a la función wait () del subproceso, el subproceso entrará en un estado estancado y el subproceso solo podrá volver al estado ejecutable después de llamar a notificar o notificar a todo el subproceso dos veces.
2. Funciones de uso común en subprocesos de clase
2.1.suspend(), resume()
1)? Parado. Después de que suspender() interrumpe un hilo, no volverá al estado ejecutable a menos que se reciba un mensaje de reanudación().
2) Al llamar a la función suspender(), el hilo no liberará su "indicador de bloqueo".
Ejemplo 11:
clase?TestThreadMethod?extends?Thread{
public?static?int?shareVar?=?0;
público?TestThreadMethod( String?nombre){
super(nombre);
}
público?sincronizado?void?run(){
if(shareVar==0){
for(int?i=0;?i<5;?i ++){
shareVar++;
if(shareVar==5){
this.suspend(); //(1)
}}
else{ p>
System.out.print(Thread. currentThread().getName());
System.out.println("?
this.resume(); //(2)
}}
}
public?class?TestThread{
public?static?void?main( String[]?args ){
TestThreadMethod?t1?=?new?
TestThreadMethod("t1");
TestThreadMethod?t2?=?new ?TestThreadMethod("t2");
t1.start( ); //(5)
//t1.start(); //(3)
t2.start(); //(4)
}}
El resultado de la ejecución es:
t2?shareVar?=?5< / p>
i. Cuando el hilo generado por t1 del código (5) se ejecuta en el código (1), el hilo entra en un estado estancado. Luego, el programador evoca el hilo generado por t2 del código (4). grupo de subprocesos. El valor de shareVar no es 0, por lo que se ejecuta la instrucción else
ii. Quizás se pregunte, ¿por qué la ejecución del código (2) no hace que t1 entre en el estado ejecutable? , t1 y t2 son subprocesos de dos objetos diferentes, y ambos códigos (1) y (2) solo realizan operaciones en el objeto actual. Por lo tanto, el resultado de ejecutar el código (1) en el subproceso generado por t1 es el subproceso actual. del objeto t1 ingresa El resultado de ejecutar el código (2) en el subproceso generado por t2 es mover todos los subprocesos estancados en el objeto t2 de regreso al estado ejecutable.
iii. Entonces, ¿ahora comentar el código (4) y eliminar los comentarios en el código (3) devolverá t1 a un estado ejecutable? El resultado es que no hay salida. ¿Por qué sucede esto? Tal vez piense que cuando el código generado por el hilo (5) llega al código (1), entra en un estado estancado y el código generado por el hilo (3) y el código generado por el hilo (5) pertenecen al mismo objeto; cuando el hilo Cuando el código generado (3) se ejecuta en el código (2), el código generado por el hilo (5) puede volver al estado ejecutable. Sin embargo, debe quedar claro que la función suspender () solo permite que el hilo actual entre en estado estancado sin liberar el "indicador de bloqueo" obtenido por el hilo actual. Por lo tanto, cuando el hilo generado por el código (5) entra en un estado estancado, el hilo generado por el código (3) aún no se puede iniciar porque el "indicador de bloqueo" del objeto actual todavía está ocupado por el hilo generado por el código (5). .
#p#2.2?sleep()
1) La función "sleep?()" tiene un parámetro que puede hacer que el hilo se detenga durante un período de tiempo específico y automáticamente Ingrese al estado ejecutable.
2) Al llamar a la función sleep?(), el hilo no liberará su "indicador de bloqueo".
Ejemplo 12:
clase?TestThreadMethod?extends?Thread{
clase?TestThreadMethod?extends?Thread{
público?estático ?int?shareVar?=?0;
público?TestThreadMethod(String?name){
super(nombre);
}
public?currentThread().getName());
System.out.println("? :?" ? +?i);
intenta{
Thread.sleep(100); //(4)
}
catch(InterruptedException?e){
System.out.println( "Interrumpido" );
}}
}
public?class?TestThread{public?static?void?main(String[]?args){
TestThreadMethod?t1?=?new?
TestThreadMethod("t1");
TestThreadMethod?t2?=?new?TestThreadMethod("t2") ;
t1.start(); (1)
t1.start(); (2)
// t2.start(); )
}}
El resultado de la ejecución es:
t1?:?0
t1?:?1
t1?:?2
t1?:?0
t1?::1
t1?::2
Se puede demostrar a partir de los resultados que aunque sleep() se ejecuta en run(), no libera el "indicador de bloqueo" del objeto, por lo tanto, a menos que el hilo del código (1) ejecute run() y libere el. "bandera de bloqueo" del objeto; de lo contrario, el hilo de código (2) nunca se ejecutará.
Si comentas el código (2) y descomentas el código (3), el resultado será:
t1?:?0
t2?:? 0
t1?:?1
t2?:?1
t1?:.2
t2?:.2
p>Dado que t1 y t2 son subprocesos para dos objetos, nunca se ejecutarán cuando t1 y t2 sean subprocesos para dos objetos.
Dado que t1 y t2 son subprocesos de dos objetos, cuando el subproceso t1 entra en estado estancado a través de sleep(), el programador llama a otros subprocesos ejecutables en el grupo de subprocesos para iniciar el subproceso t2.
Ejemplo 13:
clase?TestThreadMethod?extends?Thread{
public?static?int?shareVar?=?0;
público?TestThreadMethod( String?nombre){
super(nombre);
}
público?sincronizado?void?run(){
for(int?i=0;?i<5;?i++){
System.out. print(Thread.currentThread().getName());
System.out.println("? :?" ? +?i);
prueba{
if(Thread.currentThread().getName().equals(" t1"))
Thread.sleep(200);
else
Thread.sleep(100);
System.out .println(" ?sleep( 100);
}
catch(InterruptedException?e){
System.out.println("Interrumpido");
}}
}}
public?TestThread{public?static?void?main(String[]?args){
TestThreadMethod?t1?=?new?TestThreadMethod("t1");
TestThreadMethod?t2?=?new?TestThreadMethod("t2");
t1.start() ;}}
}
public?class?TestThread{
public?static?void?main(String[]?args){
TestThreadMethod?t1?=?new?TestThreadMethod("t1");
TestThreadMethod?t2?=?new?TestThreadMethod("t2");
t1.setPriority (Thread.MAX_PRIORITY);
t2.setPriority(Thread.MIN_PRIORITY);
t1.start();
t2.start(); p> p>
}
}
Se ejecuta como:
t1?:?0
t1?:?1t1 .start ();
}
}
El resultado de ejecución es:
1
2
3
1
2
3
#p#3. Las funciones de subprocesos comunes en la clase Object
wait(), notify() y notifyAll() son tres funciones proporcionadas por la clase java.lang.Object, que se utilizan para coordinar múltiples subprocesos para ****- Disfruté del acceso a los datos.
3.1?wait(), notify() y notifyAll()
1) La función ?wait() tiene dos formas: la primera acepta un valor de milisegundos y se utiliza para El subproceso se pausa durante un período de tiempo específico, lo que hace que el subproceso entre en un estado estancado.
La segunda forma no toma parámetros y representa waite(), que continuará deteniéndose hasta notify() o notifyAll().
2) Cuando se ejecuta notify() en un objeto, eliminará todos los subprocesos del objeto del grupo de espera de subprocesos y los colocará en el grupo de espera de bandera de bloqueo al ejecutar notify() en un objeto; , Cuando un objeto ejecuta notifyAll (), elimina todos los subprocesos del objeto del grupo de espera de subprocesos y los coloca en el grupo de espera de bandera de bloqueo.
3) Al llamar a wait(), el subproceso libera el "indicador de bloqueo" que contiene para que otros subprocesos puedan usar otros datos de sincronización en el objeto del subproceso.
Ejemplo 17:
A continuación, modificaremos el ejemplo del Ejemplo 11
class?TestThreadMethod?extends?Thread{
public ?static?int?shareVar?=?0;
public?TestThreadMethod(String?name){
super(name);
}
público?sincronizado?void?run(){
if(shareVar==0){
for(int?i=0;?i<10;? i++){
shareVar++;
if(shareVar==5){
prueba{
this.wait(); /(4)
}
catch(InterruptedException?e){}
}
}
}
}}
if(shareVar!=0){
System.out.print(Thread.currentThread().getName()); /p>
System.out.println("?shareVar?=?" ? +?shareVar);
this.notify() //(5)
}
}
}
public?TestThread{
public?t2?=?new?TestThreadMethod("t2");
t1 .start(); //(1)
//t1.start() (2)
t2.start(); /(3)
}}
El resultado de ejecución es:
t2?shareVar?=?5
Desde t1 y t2 Son dos objetos diferentes, por lo que el código de llamada del subproceso t2 (5) no puede activar el subproceso t1. Si descomentas el código (2) y comentas el código (3), el resultado será:
t1?shareVar?=?5
t1?shareVar?=?10
Esto se debe a que cuando el hilo en el código (1) llega al código (4), entra en un estado estancado y libera el estado de bloqueo del objeto. A continuación, el hilo de código (2) ejecuta run(). Dado que el valor de shareVar es 5 en este momento, ejecuta la declaración de impresión y llama al código (5) para que el hilo de código (1) entre en el estado ejecutable. Entonces el hilo del código (2) termina. Cuando se vuelve a ejecutar el hilo del código (1), ejecutará el bucle for() hasta shareVar = 10 y luego imprimirá shareVar.
#p#3.2?wait(), notify() y sincronizado
El uso de WAITE() y NOTIFY() se debe a que se aplica el "indicador de bloqueo" al objeto.
Si utiliza el "indicador de bloqueo" de un objeto, debe llamarlo en una función sincronizada o en un bloque de código sincronizado. Si se llaman dentro de una función asincrónica o un bloque de código asincrónico, se compilarán y aprobarán, pero se producirá una excepción IllegalMonitorStateException en tiempo de ejecución.
Ejemplo 18:
clase?TestThreadMethod?extends?Thread{
público?int?shareVar?=?0;
público ?TestThreadMethod(String?name) {
super(nombre);
new?Notifier(this);
}
público ?sincronizado?void?run(){
if(shareVar==0){
for(int?i=0;?i<5;?i++){ p>
shareVar++;
System.out.println("i?=?" ? +?shareVar);
prueba{
System. out.println("espera...") ;
this.wait();
}
catch(InterruptedException?e){ } p>
}}
}
}
}
}
clase ?Notificador? extiende?Thread{
privado?TestThreadMethod?ttm;
Notificador(TestThreadMethod?t){
ttm?=?t;
start();
}
public?void?run(){
mientras(verdadero){
intentar{
sleep(2000);
}
catch(InterruptedException?e){}
/*1?*/
sincronizado(ttm){
System.out.println("notificar...") ;
ttm.notify();
}}
}
}
}
¿clase pública?TestThread{
¿pública?estática? void?main(String[]?args){
TestThreadMethod?t1?=?new?TestThreadMethod("t1");
t1.start( );
}
}
Ejecutar como:
i?=?1
espera... .... p>
notificar......
i?=?2
espera......
notificar.... ..
i?=?3
espera......
notificar...... p>
i ?=?4
espera......
notificar......
i?=?5
esperar...
notificar...
4.? Discutir esperar(), notificar(), notificar a todos() y suspender(), reanudar(), dormir()
4.1? ¿La diferencia entre estos dos conjuntos de funciones?
1)? Cuando wait() hace que el hilo actual entre en un estado estancado, también liberará el "indicador de bloqueo". "ocupado por el hilo actual, de modo que los recursos de sincronización en el objeto de hilo puedan ser utilizados por otros hilos en el objeto; mientras que suspender() y
sleep() no libera el "indicador de bloqueo" ocupado por el hilo actual cuando entra en un estado estancado. "
2).
2)? El primer grupo de funciones debe llamarse en una función sincronizada o en un bloque de código sincronizado; de lo contrario, se generará un error en tiempo de ejecución; mientras que el segundo Un grupo de funciones se puede llamar en funciones asincrónicas, también se puede llamar en bloques de código sincrónicos
4.2 Compensaciones entre estos dos conjuntos de funciones
El último conjunto de funciones ya no es recomendado en Java 2. Esto se debe a que el "indicador de bloqueo" obtenido por el hilo actual no se libera cuando se llama a suspend(), lo que puede conducir fácilmente a un "punto muerto"