Mecanismo de activación y espera de aprendizaje de Java: problemas de productores y consumidores

1. Comunicación entre hilos

Significa que varios subprocesos están procesando el mismo recurso, pero las acciones de procesamiento (tareas de los subprocesos) son diferentes.

Entonces, ¿ por qué lidiar con la comunicación entre hilos?
Cuando se ejecutan varios subprocesos al mismo tiempo, la CPU cambiará los subprocesos aleatoriamente de forma predeterminada. Cuando necesitamos varios subprocesos para [completar una tarea juntos], y queremos que tengan [ejecución regular], entonces la necesidad de varios subprocesos Algunas comunicaciones coordinadas para ayudarnos a lograr una cooperación de subprocesos múltiples de un dato.

Cómo garantizar un uso eficaz de los recursos para la comunicación entre subprocesos: cuando
varios subprocesos procesan el mismo recurso y tienen diferentes tareas, la comunicación de subprocesos es necesaria para ayudar a resolver el uso u operación de la misma variable entre subprocesos. Es decir, cuando varios subprocesos operan en la misma pieza de datos, evitan la contención por la misma variable compartida. Es decir, necesitamos utilizar ciertos medios para permitir que cada hilo utilice los recursos de forma eficaz. Y este método está esperando el mecanismo de activación.

2. Espere el mecanismo de activación.

Se refiere a un mecanismo de coordinación entre varios subprocesos. Debido a que no solo hay competencia entre subprocesos, como la contención por bloqueos, también habrá mecanismos de cooperación entre subprocesos para cooperar para completar ciertas tareas.

Es decir, después de que un hilo ha realizado una operación prescrita, entra en el estado de espera (esperar ()) y espera a que otros hilos ejecuten su código designado antes de despertarlo (notificar ()); cuando hay varios hilos esperando, si Si es necesario, notifyAll () se puede utilizar para despertar todos los hilos en espera.
esperar / notificar es un mecanismo de cooperación entre hilos.

void wait()
        在其他线程调用此对象的 notify()方法或 notifyAll()方法前,导致当前线程等待
void notify()
        唤醒在此对象监视器上等待的单个线程
void notifyAll()
		唤醒在此对象监视器上等待的所有线程

【Nota】 :

  1. El mismo objeto de bloqueo debe llamar al método de espera y al método de notificación. Porque: el objeto de bloqueo correspondiente puede despertar el hilo después del método de espera llamado por el mismo objeto de bloqueo mediante una notificación.
  2. El método de espera y el método de notificación son métodos de la clase Object. Porque: el objeto de bloqueo puede ser cualquier objeto y la clase de cualquier objeto hereda la clase Object.
  3. El método de espera y el método de notificación deben utilizarse en bloques de código síncronos o funciones síncronas. Porque: estos dos métodos deben llamarse a través del objeto de bloqueo.

Caso típico: problema de productor y consumidor (venta de bollos)

[Análisis]
Inserte la descripción de la imagen aquí
[Demostración del programa]

    资源类:包子类
    设置包子的属性
    皮
    馅
    包子的状态;有true,没有false
public class BaoZi {
    
    
     String pi;
     String xian;
     //包子的状态;有true,没有false,设置初始值为false没有包子
    boolean flag = false;
}
生产者(包子铺)类:是一个线程类,可以继承Thread
设置线程任务(run):生产包子
对包子的状态进行判断
true:有包子
    包子铺调用wait方法进入等待状态
false:没有包子
    包子铺生产包子
    增加一些趣味性:交替生产两种包子
        有两种状态(%2==0)
    包子铺生产好了包子
    修改包子的状态为true有
    唤醒吃货线程,让吃货线程吃包子

注意:
    包子铺线程和吃货线程关系--->通信(互斥)
    必须采用同步技术保证两个线程只能有一个在执行
    锁对象必须保证唯一,可以使用包子对象作为锁对象
    包子铺类和吃货类就需要把包子对象作为参数传递进来
        1.需要在成员位置创建一个包子变量
        2.使用带参数的构造方法,为这个包子变量赋值
public class BaoZiPu extends Thread{
    
    

    //1.需要在成员位置创建一个包子变量
    private BaoZi bz;

    // 2.使用带参数的构造方法,为这个包子变量赋值

    public BaoZiPu(String name,BaoZi bz) {
    
    
        this.bz = bz;
    }

    //设置线程任务(run):生产包子
    @Override
    public void run() {
    
    
        //定义一个变量
        int count = 0;
        //让包子铺多生产几次包子
        while (true){
    
    
            //必须采用同步技术保证两个线程只能有一个在执行
            synchronized (bz) {
    
    
                //对包子的状态进行判断
                if (bz.flag == true) {
    
    
                    try {
    
    
                        bz.wait();
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                }

                //没有包子,被唤醒之后执行,包子铺生产包子
                //增加一些趣味性:交替生产两种包子
                System.out.println("包子铺开始做包子");
                if (count % 2 ==0) {
    
    
                    //生产 “薄皮三鲜馅包子”
                    bz.pi = "薄皮";
                    bz.xian = "三鲜馅";
                }else {
    
    
                    //生产 “冰皮五仁馅包子”
                    bz.pi = "冰皮";
                    bz.xian = "五仁馅";
                }
                count++;
                System.out.println("包子铺正在生产:" + bz.pi + bz.xian +"包子");
                //生产包子需要3秒钟
                try {
    
    
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                //包子铺生产好了包子,修改包子的状态为true
                bz.flag = true;
                //唤醒吃货线程,让吃货线程吃包子
                bz.notify();
                System.out.println("包子铺做好了" + bz.pi+bz.xian+ "包子,吃货开吃了。");
            }
        }

    }
}
消费者(吃货)类:是一个线程类,可以继承Thread
设置线程任务(run):吃包子
对包子的状态进行判断
false;么有包子
    吃货调用wait方法进入等待状态
true:有包子
    吃货吃包子
    吃货吃完包子
    修改包子的状态为false没有
    吃货唤醒包子铺线程,生产包子
public class ChiHuo extends Thread{
    
    
    //1.需要在成员位置创建一个包子变量
    private BaoZi bz;

    // 2.使用带参数的构造方法,为这个包子变量赋值
    public ChiHuo(String name,BaoZi bz) {
    
    
        super(name);
        this.bz = bz;
    }
    //设置线程任务(run):吃包子
    @Override
    public void run() {
    
    
        // 对包子的状态进行判断
        while (true){
    
    
            synchronized (bz){
    
    
                if (bz.flag == false){
    
    
                    try {
    
    
                        bz.wait();
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                }
                //被唤醒之后执行的代码,吃包子
                System.out.println("吃货正在吃" +bz.pi+bz.xian+"包子");
                //吃货吃完包子,修改包子的状态为false没有
                bz.flag = false;
                //吃货唤醒包子铺线程,生产包子
                bz.notify();
                System.out.println("吃货已经把"+bz.pi+bz.xian+"包子吃完了,包子铺开始生产包子");
                System.out.println("=============================================");
            }
        }

    }
}
测试类:
包含main方法,程序执行的入口,启动程序
创建包子对象;
创建包子铺线程,开启,生产包子;
创建吃货线程,开启,吃包子
public class Demo {
    
    
    //包含main方法,程序执行的入口,启动程序
    public static void main(String[] args) {
    
    
        //创建包子对象;
        BaoZi bz = new BaoZi();
        //创建包子铺线程,开启,生产包子;
        new BaoZiPu("包子铺",bz).start();
        //创建吃货线程,开启,吃包子
        new ChiHuo("吃货",bz).start();

    }
}

【Resultados de la operación】 :
Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/weixin_44664432/article/details/106813265
Recomendado
Clasificación