Java Multithreading 08 - Modèle producteur/consommateur

1 Présentation du concept

Dans un environnement multithread, nous avons souvent besoin de la concurrence et de la communication mutuelle de plusieurs threads. Parmi eux, il existe un important modèle de collaboration simultanée multithread, à savoir le « modèle producteur/consommateur ».

2 Présentation du rôle

producteur

Le module chargé de produire des données peut être une méthode, un objet, un thread ou un processus.

consommateur

Le module responsable du traitement des données peut être une méthode, un objet, un thread ou un processus.

tampon

Les consommateurs ne peuvent pas utiliser directement les données du producteur, il existe un « tampon » entre le producteur et le consommateur. Le producteur place les données et le contenu produits dans le « tampon », et le consommateur récupère les données à traiter dans le « tampon ».

Le tampon est au cœur de la concurrence. Les avantages de la définition d'un tampon sont les suivants :

  • Implémenter une collaboration simultanée de threads

Après avoir défini le tampon, le thread producteur n'a qu'à mettre les données dans le tampon et n'a pas besoin de vérifier la consommation du consommateur ; de même, le consommateur n'a qu'à extraire les données à traiter du tampon et n'a pas besoin de vérifier savoir ce que le producteur produit. De cette manière, la séparation du « fil producteur » et du « fil consommateur » est logiquement réalisée, et le couplage entre producteur et consommateur est découplé.

  • Résoudre l’activité inégale et améliorer l’efficacité

Lorsque le producteur tarde à produire des données, il y a toujours des données dans le tampon, ce qui n'affecte pas la consommation du consommateur ; lorsque le consommateur tarde à traiter les données, le producteur peut toujours continuer à mettre des données dans le tampon.

3 Mettre en œuvre le modèle producteur-consommateur

3.1 Créer des objets à produire et à consommer

public class Food {
    private int id;

    public Food(int id) {
        this.id = id;
    }
    
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }
}

3.2 Créer un tampon

public class BufferBlock {
    //定义存放食物的盒子
    private Food[] foods = new Food[10];
    //定义操作盒子的索引
    private int index;
    /**
     * 放食物
     */
    public synchronized void push(Food food){
        //判断盒子是否已满
        while(this.index == this.foods.length){
            try {
                //释放锁
                this.wait();
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        //唤醒领取食物的线程
        this.notify();
        this.foods[this.index] = food;
        this.index++;
    }
    /**
     * 取食物
     */
    public synchronized Food pop(){
        while(this.index == 0){
            try {
                //满足条件后,释放锁
                this.wait();
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        //唤醒放入食物的线程
        this.notify();
        this.index--;
        return this.foods[this.index];
    }
}

3.3 Créer un fil de discussion producteur

public class ProducerThread extends Thread{
    private BufferBlock block;
    public ProducerThread(BufferBlock block){
        this.block = block;
    }
    @Override
    public void run() {
        for(int i=0;i<10;i++){
            Food food = new Food(i);
            this.block.push(food);
            System.out.println("生产食物:" + food.getId());
        }
    }
}

3.4 Créer un fil de discussion consommateur

public class ConsumerThread extends Thread{
    private BufferBlock block;
    public ConsumerThread(BufferBlock block){
        this.block = block;
    }
    @Override
    public void run() {
        for(int i=0;i<10;i++){
            Food pop = this.block.pop();
            System.out.println("消费食物:" + pop.getId());
        }
    }
}

3.5 Créer une classe de test

public class Test {
    public static void main(String[] args) {
        //创建缓冲区
        BufferBlock block = new BufferBlock();
        //启动消费者线程
        new ConsumerThread(block).start();
        //启动生产者线程
        new ProducerThread(block).start();
    }
}

3.6 Sortie des résultats

Produire de la nourriture : 0

Produire de la nourriture : 1

Produire de la nourriture : 2

Produire de la nourriture : 3

Produire de la nourriture : 4

Produire de la nourriture : 5

Produire de la nourriture : 6

Nourriture consommée : 0

Nourriture consommée : 6

Nourriture consommée : 5

Nourriture consommée : 4

Nourriture consommée : 3

Nourriture consommée : 2

Nourriture consommée : 1

Produire de la nourriture : 7

Produire de la nourriture : 8

Produire de la nourriture : 9

Nourriture consommée : 9

Nourriture consommée : 8

Nourriture consommée : 7

4 Résumé

Modèle producteur-consommateur :

1 Producteurs et consommateurs partagent la même ressource, et producteurs et consommateurs sont interdépendants et conditionnés les uns aux autres.

2 Pour les producteurs, avant que les données ne soient produites, les consommateurs doivent entrer dans un état d'attente ; une fois les données produites, les consommateurs doivent être immédiatement informés de leur consommation.

3 Pour les consommateurs, après la consommation, ils doivent informer le producteur que la consommation est terminée et ils doivent continuer à produire de nouvelles données pour la consommation.

4 On voit également que le tampon est important pour ce mode : pendant le travail, il est principalement implémenté à l'aide de files d'attente de messages (divers MQ, tels que kafka, ActiveMQ, RockerMQ, RabbitMQ, etc.).

 

Je suppose que tu aimes

Origine blog.csdn.net/QQ156881887/article/details/129171991
conseillé
Classement