Synchronisez sur BlockedQueue
-
21-09-2019 - |
Question
J'ai un morceau de code que je passe en revue (en utilisant FindBugs ).
public class MyClass{
...
private BlockedQueue q = new LinkedBlockingQueue<MyData>(1000);
private static final batchSize = 1000;
public boolean testMethod(){
boolean done = false;
synchronized(q){
if(q.size == batchSize){
q.notify();
done = true;
}
}
return done;
}
Quand je lance FindBugs sur ce morceau de code, il se plaint que -
Cette méthode effectue une synchronisation un objet qui est une instance d'une classe de la java.util.concurrent colis (ou ses sous-classes). Les instances de ces classes ont leur propre des mécanismes de contrôle de concurrence qui sont distincts et incompatibles avec l'utilisation du mot-clé synchronisée.
Si je commente le morceau de code synchronisé synchronized(q){
, il se plaint -
Cette méthode appelle Object.notify () ou Object.notifyAll () sans évidemment maintenir un verrou sur l'objet. Appel notifier () ou notifyAll () sans une serrure tenue entraînera une IllegalMonitorStateException étant jeté
Comment puis-je mettre en œuvre cette méthode pour qu'il passe la validation FindBugs? La mise en œuvre en haut à droite une pour la notification dans les cas pour les classes simultanées?
Merci.
La solution
notify()
va de pair avec wait()
et ne doit pas être utilisé avec des classes de java.util.concurrent
.
BlockingQueue utilise des mécanismes internes pour bloquer sur un put()
s'il n'y a pas d'espace pour plusieurs éléments ou sur poll()
s'il n'y a aucun élément à consommer. Vous ne devez pas se soucier de cela.
Autres conseils
La première erreur est indiquant que vous ne devriez pas utiliser des contrôles de synchronisation primitives sur les classes de java.util.concurrent (comme BlockingQueue).
En général, cela est une bonne pratique car ils prennent en charge la synchronisation pour vous. J'imagine qu'il ya une meilleure façon de résoudre votre problème à portée de main. Quel est le problème réel que vous essayez de résoudre?
La deuxième erreur est causée par le fait que vous devez posséder le verrouillage / moniteur d'un objet (par sychronizing dessus) pour appeler wait / informer / notifyAll sur elle
BlockingQueue est un synchroniseur - objet coordonne le flux de contrôle de fils à base de son état et ainsi contrôler le débit de fils producteurs / consommateurs car prendre et mettre bloc jusqu'à ce que la file d'attente passe à l'état souhaité (non vide ou non complète).
Aussi bonnes pratiques dans la programmation suppose que la concurrence attente et de notification sont placés dans la boucle while.