Mecanismo de notificación de espera de subprocesos múltiples

Tabla de contenido
  • ¿Qué es el mecanismo de notificación en espera?
  • A la espera de la realización del mecanismo de notificación
  • notificar no liberará el objeto de bloqueo inmediatamente
  • interrupt interrumpirá la espera del hilo
  • La diferencia entre notificar y notificar a todos
  • Uso de espera (larga)

¿Qué es el mecanismo de notificación en espera?

Plataforma de cupones https://www.cqfenfa.com/

En un solo hilo, la operación a ejecutar debe cumplir ciertas condiciones antes de que pueda ejecutarse. Puede poner esta operación en un bloque de instrucciones if.

En la programación de subprocesos múltiples, es posible que la condición del subproceso A no se satisfaga, sino solo temporalmente. Posteriormente, otros subprocesos B pueden actualizar la condición para que se satisfaga la condición del subproceso A. El subproceso A puede suspenderse hasta que se cumplan sus condiciones. Un subproceso despierta

Atomic{
 while(条件不成立)
 {
 等待
 }
 条件满足后,当前线程被唤醒
}

A la espera de la realización del mecanismo de notificación

El método Wait en la clase de objeto puede hacer que el código del hilo actual suspenda la ejecución hasta que se le notifique o se interrumpa

Nota:

(1) El método de espera solo puede ser llamado por el objeto de bloqueo en el bloque de código de sincronización

(2) Llame al método de espera, el hilo actual liberará el bloqueo

public class Text16_5 {
    public static void main(String[] args) throws InterruptedException {
        String text="hello";
        System.out.println("同步前代码块");
        synchronized (text)
        {
            System.out.println("同步代码块开始");
            text.wait();
            System.out.println("同步代码块结束");
        }
        System.out.println("全部结束");
    }
}

imagen-20210316211333325

Debido a que se llama al método de espera del objeto de bloqueo, el objeto de bloqueo se libera y está en un estado de espera, y esperará eternamente si no se despierta.

El método de notificación de la clase de objeto puede despertar el hilo. Este método también debe estar sincronizado en el bloque de código. Es llamado por el objeto de bloqueo. Llamar a esperar / notificar sin usar el objeto de bloqueo informará la excepción IiegalMonuitorStateExeption. Si hay varios subprocesos en espera, el método de notificación solo puede activar uno de ellos. Después de llamar al método de notificación en el bloque de código sincronizado, el objeto de bloqueo no se liberará inmediatamente. El objeto de bloqueo no se liberará hasta que se ejecute el bloque de código sincronizado actual Generalmente, la notificación se coloca al final del bloque de código sincronizado.

synchronized(锁对象)
{
  //执行修改保护条件的代码
  //唤醒其他线程
  锁对象.notify();
}
public class TextNotify {
    public static void main(String[] args) throws InterruptedException {
        String text="hello";
        Thread t1=new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (text)
                {
                    System.out.println("同步代码块开始");
                    try {
                        text.wait();//线程等待 
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("同步代码块结束");
                }
            }
        });
        Thread t2=new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (text)
                {
                    System.out.println("线程开始唤醒");
                    text.notify();
                    System.out.println("线程结束唤醒");
                }
            }
        });
        t1.start();//开启t1线程 t1等待
        Thread.sleep(3000);//睡眠3秒 确保t1处于等待状态
        t2.start();//唤醒t1线程
    }
}

imagen-20210316214002434

notificar no liberará el objeto de bloqueo inmediatamente

Caso:

import java.util.ArrayList;
import java.util.List;

public class NotifyText2 {
    public static void main(String[] args) throws InterruptedException {
        List<String> strings=new ArrayList<>();
        Thread t1=new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (strings)
                {
                    System.out.println("线程1开始等待");
                    try {
                        strings.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("线程1被唤醒");
                }
            }
        });
        Thread t2=new Thread(new Runnable() {
            @Override
            public void run() {
               synchronized (strings)
               {
                   for (int i = 0; i <10 ; i++) {
                       strings.add("data"+i);
                       System.out.println("线程2添加了"+(i+1));
                       if(strings.size()==5)
                       {
                           strings.notify();
                           System.out.println("线程2被唤醒");
                       }
                   }
               }
            }
        });
        t1.start();
        Thread.sleep(1000);
        t2.start();
    }
}

El código del subproceso 2 aún no se ha ejecutado y el bloqueo aún se está ejecutando sin ser liberado de inmediato. Debe esperar hasta que se ejecuten todos los bloques de código antes de liberarlo.

imagen-20210316220423289

interrupt interrumpirá la espera del hilo

public class InterruptText {
    private static  final String name=new String();
    public static void main(String[] args) throws InterruptedException {

        Thread t1=new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (name)
                {
                    try {
                        System.out.println("同步代码块开始");
                        name.wait();
                        System.out.println("同步代码块结束");
                    } catch (InterruptedException e) {
                        System.out.println("wait被中断"+e);
                    }
                }
            }
        });
        t1.start();
        Thread.sleep(2000);
        t1.interrupt();
    }
}

Resulta que el objeto de bloqueo necesita ejecutar el bloque de código de sincronización para liberar el objeto de bloqueo. Si se encuentra una excepción durante el proceso de ejecución, el hilo se terminará y el objeto de bloqueo se liberará. Llamar al método de espera también liberará el objeto de bloqueo.

imagen-20210317202003190

La diferencia entre notificar y notificar a todos

Notify solo puede despertar uno a la vez. Si hay varios subprocesos en espera, solo uno de ellos se puede despertar al azar. Para despertar todos los subprocesos en espera, debe llamarse a notifyAll.

public class InterruptText {
    private static  final String name=new String();
    public static void main(String[] args) throws InterruptedException {
        String str=new String();
        NotifyAll notifyAll=new NotifyAll(str);
        NotifyAll notifyAl2=new NotifyAll(str);
        NotifyAll notifyAll3=new NotifyAll(str);
        notifyAll.setName("线程一");
        notifyAl2.setName("线程二");
        notifyAll3.setName("线程三");
        notifyAll.start();
        notifyAl2.start();
        notifyAll3.start();
        Thread.sleep(2000);//休眠两秒
        synchronized (str)
        {
            //str.notify();只能随机唤醒一个
            str.notifyAll();//唤醒全部线程
        }
    };
     static class NotifyAll extends Thread
    {
        private    String name;
        private  NotifyAll(String name)
        {
            this.name=name;
        }
                @Override
                public void run() {
                    synchronized (name)
                    {
                        try {
                            System.out.println(Thread.currentThread().getName()+"同步代码块开始");
                            name.wait();
                            System.out.println(Thread.currentThread().getName()+"同步代码块结束");
                        } catch (InterruptedException e) {
                            System.out.println("wait被中断"+e);
                        }
                    }
                }

    }
}

imagen-20210317221240524

Si el mal de llamar anotificar () sólo una vez puede despertar uno de los hilos, los otros hilos en espera todavía están en estado de espera y se pierde la señal de notificación, este fenómeno se denomina pérdida de señal.

Uso de espera (larga)

Método de espera (largo) con parámetros, ninguna operación dentro de un tiempo especificado se despertará automáticamente

Supongo que te gusta

Origin blog.csdn.net/nidongla/article/details/115029321
Recomendado
Clasificación