Este artículo estudia principalmente el código de muestra de la aplicación de la condición de bloqueo de la condición de concurrencia Java, de la siguiente manera.
La condición desglosa los métodos del monitor de objetos (espere, notifique y notifique) en objetos completamente diferentes para que al combinar estos objetos con cualquier implementación de bloqueo, cada objeto proporcione múltiples conjuntos de espera (conjunto de espera). Entre ellos, el bloqueo reemplaza el uso de métodos y declaraciones sincronizados, y la condición reemplaza el uso de métodos de monitor de objetos.
Dado que la condición se puede usar para reemplazar Wait, Notify y otros métodos, podemos comparar el código de comunicación entre hilos escrita antes y echar un vistazo al problema original:
Hay dos hilos. El hilo infantil se ejecuta 10 veces primero, luego el hilo principal se ejecuta 5 veces, luego cambia al hilo infantil ejecuta 10 y luego el hilo principal se ejecuta 5 veces ... Este viaje redondo es 50 veces.
Utilicé Wait y notifiqué para implementarlo antes, pero ahora uso la condición para reescribirlo, el código es el siguiente:
Condición de clase pública Condición Comunicación {public static void main (string [] args) {Business Business = New Business (); new Thread (new Runnable () {// Abra un hilo infantil @override public void run () {for (int i = 1; i <= 50; i ++) {Bussiness.sub (i);}}}). Start (); /// Método principal para (INT (inti (inti (inti (inti (inti (inti (inti (inti (inti (inti. 50; {condición.aWait (); // use condición para llamar al método de espera} capt (excepción e) {// tODO generado automático blocke.printstackTrace ();}} for (int j = 1; j <= 10; j ++) {system.println ("secuencia de subprojes de" + j + ", bucle de" + i);} bshoul falso; condición.signal (); // use la condición para enviar una señal de despertar y despertar un cierto} finalmente {lock.unlock ();}} public void main (int i) {Lock.lock (); try {while (bshouldSub) {try {condición.eit.await (); // Use condición para llamar al método de espera} (excepción) {// a aDO-generated. blocke.printstackTrace ();}} for (int j = 1; j <= 10; j ++) {system.out.println ("secuencia de hilo principal de" + j + ", bucle de" + i);} bshouldsub = true; condy.signal (); // Use condición para enviar una señal de despertar, despertar un cierto}Desde el punto de vista del código, la condición se usa junto con el bloqueo. Sin bloqueo, la condición no se puede usar, porque la condición se crea a través del bloqueo. Este uso es muy simple. Siempre que domine el uso de sincronizado, espere y notifique, puede dominar completamente el uso de bloqueo y condición.
Lo anterior utiliza bloqueo y condición en lugar de métodos sincronizados y monitores de objetos para realizar la comunicación entre dos hilos. Ahora escribamos una aplicación un poco más avanzada: simule la cola de bloqueo del búfer.
¿Qué es un búfer? Por ejemplo, hay muchas personas que desean enviar mensajes ahora. Soy una estación de tránsito y quiero ayudar a otros a enviar mensajes. Así que ahora necesito hacer dos cosas. Una cosa es recibir mensajes enviados por el usuario y ponerlos en el búfer en orden. La otra cosa es sacar mensajes enviados por el usuario en orden desde el búfer y enviarlos.
Ahora resumir este problema real: un búfer es una matriz. Podemos escribir datos en la matriz o sacar datos de la matriz. Las dos cosas que necesito hacer son iniciar dos hilos, uno para almacenar datos y el otro para obtener datos. Pero el problema es que si el búfer está lleno, significa que hay demasiados mensajes recibidos, es decir, el mensaje enviado es demasiado rápido, y otro hilo de mi vida no es suficiente para enviarlo, lo que resulta en que el búfer se quede fuera, por lo que el hilo de almacenamiento de datos debe bloquearse y dejarlo esperar; Por el contrario, si lo reenvío demasiado rápido, y ahora todos los contenidos del búfer han sido enviados por mí y el usuario ha enviado ningún mensaje nuevo, entonces el hilo de la adquisición de datos debe bloquearse en este momento.
Ok, después de analizar la cola de bloqueo de este búfer, usemos la tecnología de condición para implementarla:
Buffer de clases {final de bloqueo final = new ReEntrantLock (); // Defina una condición final de bloqueo notfull = Lock.newCondition (); // Defina la condición de condición de condición NotEtimty = Lock.NewCondition (); // Define ConditionFinal Object [] items = Nuevo objeto [10]; // Para la siguiente simulación, establece el tamaño del bloque de bloqueas a 10, no se seta demasiado grande, no se seta, no lo hagas, no se seta. count ;/ los subíndices de matriz se utilizan para calibrar la posición // los datos de almacenamiento en la cola public void put (objeto x) lanza interruptedException {lock.lock (); // bloquear try {while (count == items.length) {System.out.println (thread.currentThread (). getName () + "Bloqueado, los datos no se pueden guardar para el tiempo para el tiempo para el tiempo para el tiempo para el tiempo para el tiempo para el tiempo para el tiempo para el tiempo Ser! "); NotfUll.Await (); // Si la cola está llena, luego bloquee el hilo del almacenamiento de datos, esperando que se despierte} // Si no está lleno, almacene los elementos [putptr] = x; if (++ putptr == items.length) // Este es el juicio que llega al final del array. Si se alcanza, regrese al comienzo putptr = 0; ++ count; // número de mensajes System.out.println (Thread.CurrentThread (). GetName () + "Guardar el valor:" + x); Notempty.signal (); // bien, ahora hay datos en la cola. Despertar el hilo con la cola vacía y puede obtener los datos} Finalmente {lock.unlock (); // Descargar el bloqueo}} // Betch Data del objeto público de cola Take () lanza InterruptedException {Lock.lock (); // Lock Try {while ((= 0) {System.Println (thread.currentThread (). Tiempo de ser! "); Notempty.Await (); // Si la cola está vacía, entonces el subproceso bloquea los datos para recuperar el hilo, esperando a que System.out.println (thread.currentThread (). GetName () + "Obtenga el valor:" + x); notfull.signal (); // está bien, ahora hay una ubicación en la cola. Despierta el hilo lleno de la cola y podrás almacenar datos. Return x;} Finalmente {Lock.unlock (); // Lock}}}Este programa es clásico, lo sacé de la documentación oficial de JDK y agregué comentarios. Hay dos condiciones definidas en el programa, que se utilizan para ejecutar los dos hilos, y esperar y despertar respectivamente. La idea es clara y el programa también es muy robusto. Se puede considerar una pregunta, ¿por qué necesita usar dos códigos? Debe haber una razón para este diseño. Si usa una condición, ahora suponga que la cola está llena, pero hay 2 hilos A y B que almacenan datos al mismo tiempo, entonces todos entran en el sueño. Ok, ahora otro hilo lleva uno y luego despierta uno de los hilos A, luego puede guardarlo. Después de ahorrar, un despierta otro hilo. Si B se despierta, habrá un problema, porque la cola está llena en este momento y B no puede almacenarlo. Si B almacena, sobrescribirá el valor que no se ha recuperado. Debido a que se usa una condición, tanto el almacenamiento como la retirada usan esta condición para dormir y despertarse, y se desordenará. En este punto, puede comprender el uso de esta condición. Ahora probemos el efecto de la cola de bloqueo anterior:
public class BoundedBuffer {public static void main (string [] args) {buffer buffer = new buffer (); for (int i = 0; i <5; i ++) {// abre 5 hilos para almacenar datos en el buffer new hild (new runNable () {@override public void run () {intit {buffer.put.put (new Random (). Nextint (1000)) (InterruptedException e) {E.PrintStackTrace ();}}}). Start ();} for (int i = 0; i <10; i ++) {// Abrir 10 subprocesos para obtener datos del nuevo hilo de buffer (new runnable () {@Override public void run () {try {buffer.take (); // f data de los datos de runnable () {@Override {E.PrintStackTrace ();}}}). Start ();}}}}Deliberadamente habilité solo 5 hilos para almacenar datos y 10 hilos para obtener datos, solo para que se bloqueara para obtener datos y ver los resultados de la operación:
¡Thread-5 está bloqueado y los datos no se pueden recuperar por el momento!
¡Thread-10 está bloqueado y los datos no se pueden recuperar por el momento!
Tema-1 Valor guardado: 755
Hild-0 Valor guardado: 206
Hild-2 Valor guardado: 741
Hild-3 Valor guardado: 381
Hilo-14 Valor eliminado: 755
Tema-4 Valor guardado: 783
Thread-6 elimina el valor: 206
Hilo-7 Valor eliminado: 741
Hilo-8 Valor eliminado: 381
Thread-9 elimina el valor: 783
¡Thread-5 está bloqueado y los datos no se pueden recuperar por el momento!
¡Thread-11 está bloqueado y los datos no se pueden recuperar por el momento!
¡Thread-12 está bloqueado y los datos no se pueden recuperar por el momento!
¡Thread-10 está bloqueado y los datos no se pueden recuperar por el momento!
¡Thread-13 está bloqueado y los datos no se pueden recuperar por el momento!
A partir de los resultados, podemos ver que los hilos 5 y 10 se ejecutan primero, y encuentran que no hay en la cola, por lo que están bloqueados y duermen allí. Solo pueden obtenerlo hasta que se almacene un nuevo valor en la cola. Sin embargo, no tienen suerte, y los datos almacenados son tomados primero por otros hilos. Jaja ... Pueden ejecutarlo varias veces más. Si desea ver que los datos almacenados están bloqueados, puede configurar el hilo para obtener los datos un poco menos, y no los configuraré aquí.
Sigue siendo la misma pregunta que antes. Ahora deje que tres hilos lo ejecuten. Echemos un vistazo a la pregunta:
Hay tres hilos, el hilo infantil 1 se ejecuta 10 veces primero, el hilo infantil 2 se ejecuta 10 veces, luego el hilo principal se ejecuta 5 veces, luego cambia a hilo infantil 1 se ejecuta 10 veces, el hilo infantil 2 se ejecuta 10 veces, el hilo principal se ejecuta 5 veces ... Este viaje redondo es 50 veces.
Si no usa la condición, es realmente difícil de hacer, pero es muy conveniente hacerlo con condición. El principio es muy simple. Definir tres condiciones. Después de que el hilo infantil 1 se ejecuta, el hilo infantil 2 despierta el hilo principal, y el hilo principal despierta el hilo infantil 1. El mecanismo de activación es similar al búfer anterior. Echemos un vistazo al código a continuación, es fácil de entender.
public class ThreeconditionCommunication {public static void main (string [] args) {Business Business = new Business (); new Thread (new Runnable () {// Abra un hilo infantil @Override public void run () {for (int i = 1; i <= 50; i ++) {Bussiness.sub1 (i);}}}}). {// Iniciar otro hilo infantil @Override public void run () {for (int i = 1; i <= 50; i ++) {Bussiness.sub2 (i);}}}). Start (); // Método principal PRINCIPAL PRINCIPAL PARA (INT I = 1; i <= 50; i ++) {Bussiness.Main (i);}}} Class de clase STATIC {Lock Lock Lock = condición1 = Lock.newCondition (); // La condición es una condición2 = Lock.newCondition (); condición condicionMain = Lock.newCondition (); private int bshouldsub = 0; public void sub1 (int i) {lock.lock (); try {while (bshheuldsub! = 0) {try {condicion1.await (); // use condición para llamar a await » {// TODO Generado automático BLOCKE.PRINTSTACKTRACE ();}} para (int j = 1; j <= 10; j ++) {System.out.println ("Sub1 Stractuence de" + j + ", bucle de" + i);} bshoulDsub = 1; condicion2.Signal (); // Let Thread Execute Upute {Lock.unlock ();}} public void sub2 (int i) {Lock.lock (); try {while (bshouldsub! = 1) {try {condición2.await (); // use condición para llamar al método de espera} capt (excepción e) {// todo auto-generated catch blocke.printstacktrace ();}}} para (int j = 1; J = 1; J = 1; J = 1; J = 1; j ++) {system.out.println ("Sub2 secuencia de hilo de" + j + ", bucle de" + i);} bshouldsub = 2; condiciónmain.signal (); // deja que el hilo principal ejecute} finalmente {lock.Onslock ();}} public void principal (int i) {Lock.Lock (); Try {while (bshouldsub! {condiciónMain.Await (); // Use condición para llamar al método de espera} Catch (Exception e) {// tODO Generado automático BLOCKE.PRINTSTACKTRACE 0; condición1.signal (); // deja que el hilo 1 se ejecute} finalmente {lock.unlock ();}}}}El código parece un poco largo, pero es una ilusión y la lógica es muy simple. Eso es todo para resumir la tecnología de condición en los hilos.
Lo anterior es todo el contenido de este artículo sobre el ejemplo del código de aplicación de la condición de bloqueo de la condición de concurrencia Java. Espero que sea útil para todos. Los amigos interesados pueden continuar referiéndose a otros temas relacionados en este sitio. Si hay alguna deficiencia, deje un mensaje para señalarlo. ¡Gracias amigos por su apoyo para este sitio!