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.).