Java multihilo (caso + análisis) parte intermedia: comunicación de subprocesos

Conceptos básicos de Java multiproceso (caso + análisis)
Java multithreading (caso + análisis) parte avanzada: modo perezoso seguro para subprocesos, problema de bloqueo de subprocesos
Java multihilo (caso + análisis) parte intermedia: comunicación de subprocesos
Java multiproceso (caso + análisis) JDK5.0 nuevo método de creación de subprocesos

1. Ejemplo 1: Ejemplos de comunicación por hilo

1. Utilice dos hilos para imprimir 1-100. Hilo 1, hilo 2, impresión alternativa

Utilice esperar y notificar

package com.itzheng.java2;
/*
线程通信的例子:使用两个线程打印1-100。线程1,线程2,交替打印
说明:
 */
class Number implements  Runnable{
    
    
    private int number = 1;
    @Override
    public void run() {
    
    
        while (true){
    
    
            synchronized (this){
    
    
                notify();//唤醒等待的(wait)的线程
                if(number <= 100){
    
    
                    try {
    
    
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                  System.out.println(Thread.currentThread().getName()+":"+number);
                    number++;
                    try {
    
    
                        //使得调用如下wait()方法的线程进入阻塞状态
                        wait();
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                }else {
    
    
                    break;
                }
            }
        }
    }
}
public class CommunicationTest {
    
    
    public static void main(String[] args) {
    
    
        Number number = new Number();
        Thread t1 = new Thread(number);
        Thread t2 = new Thread(number);
        t1.setName("线程1");
        t2.setName("线程2");
        t1.start();
        t2.start();
    }
}

Inserte la descripción de la imagen aquí

(1) Tres métodos involucrados en la comunicación de subprocesos: (solo puede aparecer en bloques de código sincronizados y métodos sincronizados)

(1) wait (): una vez que se ejecuta este método, el hilo actual entra en el estado de bloqueo y libera el monitor de sincronización.
(2) notificar (): Una vez que se ejecuta este método, se despertará un hilo que estaba esperando ().
Si hay varios subprocesos wait (), se despierta el que tiene mayor prioridad.
(3) notifyAll (): Una vez que se ejecute este método, se despertará todo un hilo que estaba esperando ().

(2) Descripción:

(1) esperar (), notificar (), notificar a todos () estos tres métodos deben usarse en bloques de código síncronos o métodos síncronos, y son llamados por este objeto

Inserte la descripción de la imagen aquí

2. Cualquier objeto como monitor de sincronización (definir objeto de objeto)

(1) La persona que llama de los tres métodos de esperar (), notificar (), notificar a todos () debe ser un monitor síncrono en el bloque de código síncrono o en el método síncrono.
De lo contrario, habrá IllegalMonitorStateException异常
(2) esperar (), notificar (), notificar a todos () Estos 3 métodos están definidos en la clase java.lang.Object

package com.itzheng.java2;
/*
线程通信的例子:使用两个线程打印1-100。线程1,线程2,交替打印
 */
class Number implements  Runnable{
    
    
    private int number = 1;
    private Object obj = new Object();
    @Override
    public void run() {
    
    
        while (true){
    
    
            synchronized (obj){
    
    
                obj.notify();//唤醒等待的(wait)的线程
                if(number <= 100){
    
    
                    try {
    
    
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()+":"+number);
                    number++;
                    try {
    
    
                        //使得调用如下wait()方法的线程进入阻塞状态
                        obj.wait();
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                }else {
    
    
                    break;
                }
            }
        }
    }
}
public class CommunicationTest {
    
    
    public static void main(String[] args) {
    
    
        Number number = new Number();
        Thread t1 = new Thread(number);
        Thread t2 = new Thread(number);
        t1.setName("线程1");
        t2.setName("线程2");
        t1.start();
        t2.start();
    }
}

Dos, resumen de los puntos clave y difíciles

1. ¿Cuáles son las similitudes y diferencias entre dormir () y esperar ()?

(1) El mismo punto: una vez que se ejecuta el método, el hilo actual puede entrar en el estado de bloqueo.
(2) Diferencias:

1) La ubicación de las dos declaraciones de método es diferente: sleep () se declara en la clase Thread y wait () se declara en la clase
Object.2) Los requisitos de llamada son diferentes: se puede llamar a sleep () en cualquier escena requerida. wait () debe usarse en un bloque de código sincronizado o un método sincronizado.
3) Preguntas sobre si liberar un monitor sincronizado: si ambos métodos se usan en un bloque de código sincronizado o método sincronizado, el método sleep () no liberará el bloqueo, espere ( ) Liberará el bloqueo.

3. Ejemplo 2: Problema del productor y del consumidor (aplicación de la comunicación por hilo)

● El productor (Productor) entrega el producto al empleado (Empleado) y al consumidor (Cliente) del empleado.

Producto eliminado, el empleado solo puede retener un número fijo de productos (por ejemplo: 20), si los productores intentan
producir más producto, el empleado llamará al productor a pausa, si hay vacantes, almacene y luego pasará el producto por
producción de conocimiento Los productores continúan produciendo: si no hay productos en la tienda, el empleado le dirá al consumidor que espere,
si hay productos en la tienda, luego notificará al consumidor que se lleve el producto.

● Aquí pueden surgir dos problemas:

➢ Cuando el productor es más rápido que el consumidor, el consumidor perderá algunos datos.
➢ Cuando el consumidor es más rápido que el productor, el consumidor obtendrá los mismos datos.

Implementación del código: ejemplos de preguntas (problema productor / consumidor)

package com.itzheng.java2;

/*

线程通信的应用:金典例题:生产者/消费者问题

取走产品,店员一次只能持有固定数量的产品(比如:20),如果生产者试图
生产更多的产品,店员会叫生产者停一下,如果店中有空位放产品了再通
知生产者继续生产:如果店中没有产品了,店员会告诉消费者等- - 下,如
果店中有产品了再通知消费者来取走产品。

分析:
1、是否是多线程的问题?是,生产者线程,消费者线程
2、是否共享数据的问题?是,店员(或产品)
3、如何来解决线程的安全问题?同步机制,有三种方法
4、是否涉及到线程的通信?是
创建Clerk办事情的对象,作为同步监视器
创建Producer:生产者
创建Consumer:消费者
分别调用对应的start方法
两个线程分别调用Clerk当中的方法,同步监视器就是Clerk对象,只有当生产完毕后才可以执行消费
 */

class Clerk{
    
    
    private int productCount = 0;
    //生产产品
    public synchronized void produceProduct() {
    
    
        if(productCount < 20){
    
    
            productCount++;
            System.out.println(Thread.currentThread().getName() + ":开始生产第" + productCount + "个产品");
            notify();//唤醒线程
        }else{
    
    
            //等待
            try {
    
    
                wait();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }
    //消费产品
    public synchronized void consumerProduct() {
    
    
        if(productCount > 0){
    
    
            System.out.println(Thread.currentThread().getName() + ":开始消费第" + productCount + "个产品");
            productCount--;
            notify();//唤醒线程
        }else {
    
    
            //等待
            try {
    
    
                wait();
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
        }
    }
}
class Producer extends  Thread {
    
    //生产者
    private Clerk clerk;
    public Producer(Clerk clerk) {
    
    
        this.clerk = clerk;
    }
    @Override
    public void run() {
    
    
        System.out.println(getName() + ":" + ":开始生产产品。。。。");
        while (true){
    
    
            try {
    
    
                Thread.sleep(10);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            clerk.produceProduct();
        }
    }
}
class Consumer extends Thread{
    
    //消费者
    private Clerk clerk;

    public Consumer(Clerk clerk) {
    
    
        this.clerk = clerk;
    }

    @Override
    public void run() {
    
    
        System.out.println(getName() + ":" + ":开始消费产品。。。。");
        while (true){
    
    
            try {
    
    
                Thread.sleep(20);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            clerk.consumerProduct();
        }
    }
}
public class ProductTest {
    
    
    public static void main(String[] args) {
    
    

        Clerk clerk = new Clerk();
        Producer p1 = new Producer(clerk);
        p1.setName("生产者一");

        Consumer c1 = new Consumer(clerk);
        c1.setName("消费者一");

        Consumer c2 = new Consumer(clerk);
        c2.setName("消费者二");

        p1.start();
        c1.start();
        c2.start();
    }
}

Inserte la descripción de la imagen aquí

Conceptos básicos de Java multiproceso (caso + análisis)
Java multithreading (caso + análisis) parte avanzada: modo perezoso seguro para subprocesos, problema de bloqueo de subprocesos
Java multihilo (caso + análisis) parte intermedia: comunicación de subprocesos
Java multiproceso (caso + análisis) JDK5.0 nuevo método de creación de subprocesos

Supongo que te gusta

Origin blog.csdn.net/qq_44757034/article/details/110800843
Recomendado
Clasificación