Question

I ai une file d'attente de blocage des objets.

Je veux écrire un thread qui bloque jusqu'à ce qu'il y est un objet sur la file d'attente. Semblable à la fonctionnalité fournie par BlockingQueue.take ().

Cependant, comme je ne sais pas si je serai en mesure de traiter l'objet avec succès, je veux juste jeter un regard () et non supprimer l'objet. Je veux enlever l'objet que si je suis capable de le traiter avec succès.

Alors, je voudrais une fonction coup d'oeil de blocage (). À l'heure actuelle, coup d'oeil () retourne juste si la file d'attente est vide selon les javadocs.

Est-ce que je manque quelque chose? Y at-il une autre façon d'obtenir cette fonctionnalité?

EDIT:

Toute réflexion sur si je viens d'utiliser un fil file d'attente sûre et jeté un œil et je dormais à la place?

public void run() {
    while (!exit) {
        while (queue.size() != 0) {
            Object o =  queue.peek();
            if (o != null) {
                if (consume(o) == true) {
                    queue.remove();
                } else {
                    Thread.sleep(10000); //need to backoff (60s) and try again
                }
            }
        }
        Thread.sleep(1000); //wait 1s for object on queue
    }
}

Notez que je n'ai qu'un fil à la consommation et un (séparé) fil de producteur. Je suppose que cela ne soit pas aussi efficace que l'utilisation d'un BlockingQueue ... Tous les commentaires apprécié.

Était-ce utile?

La solution

Vous pouvez utiliser un LinkedBlockingDeque et enlever physiquement l'élément de la file d'attente (en utilisant takeLast()), mais remplacer de nouveau à la fin de la file d'attente si le traitement échoue en utilisant putLast(E e). Pendant ce temps, vos « producteurs » ajouteraient des éléments à la avant de la file d'attente en utilisant putFirst(E e).

Vous pouvez toujours résumer ce comportement au sein de votre propre implémentation de Queue et de fournir une méthode de blockingPeek() qui effectue takeLast() suivi par putLast() les coulisses du LinkedBlockingDeque sous-jacente. Par conséquent du point de vue du client appelant est jamais supprimé l'élément de votre file d'attente.

Autres conseils

  

Cependant, comme je ne sais pas si je serai en mesure de traiter l'objet avec succès, je veux juste jeter un regard () et non supprimer l'objet. Je veux enlever l'objet que si je suis capable de le traiter avec succès.

En général, ce n'est pas thread-safe. Et si, après avoir peek() et de déterminer que l'objet peut être traité avec succès, mais avant take() pour enlever et traiter, un autre thread prend cet objet?

La seule chose que je suis conscient que cela est href="http://commons.apache.org/collections/" rel="nofollow noreferrer"> Apache Commons Collections :

  

Si l'obtenir ou supprimer est appelé   un tampon vide, le thread appelant   attend la notification qu'un ajout ou   addAll opération terminée.

get() est équivalent à peek(), et un Buffer peut être fait agir comme BlockingQueue en décorant un UnboundedFifoBuffer avec BlockingBuffer

Pourriez-vous aussi il suffit d'ajouter une file d'attente d'écouteur d'événement à votre file d'attente de blocage, alors quand quelque chose est ajouté à la (blocage) file d'attente, envoyer un événement hors à vos auditeurs? Vous pourriez avoir votre bloc de fil jusqu'à ce qu'il soit méthode actionPerformed a été appelé.

La réponse rapide est, non il n'y a pas vraiment une façon un coup d'oeil de blocage, une file d'attente barre mise en œuvre de blocage avec un coup d'oeil de blocage () vous-même.

  

Est-ce que je manque quelque chose?

peek () peut être gênant avec la concurrence -

  • Si vous ne pouvez pas traiter votre coup d'oeil () 'd message -. Il sera laissé dans la file d'attente, sauf si vous avez plusieurs consommateurs
  • Qui va faire l'objet de la file d'attente si vous ne pouvez pas le traiter?
  • Si vous avez plusieurs consommateurs, vous obtenez une condition de course entre vous peek () 'ING et un autre thread traitement également des éléments, ce qui entraîne dans le traitement ou pire double.

On dirait que vous pourriez être mieux réellement supprimer l'élément et traiter à l'aide d'un motif de chaîne de responsabilité

Edit: Re: Votre dernier exemple: Si vous avez seulement 1 consommateur, vous ne serez jamais se débarrasser de l'objet sur la file d'attente - à moins qu'il soit mis à jour dans le même temps - dans ce cas, vous feriez mieux d'être très très prudent sécurité des threads et ne devrait probablement pas mettre l'élément dans la file d'attente de toute façon.

On dirait que BlockingQueue lui-même n'a pas la fonctionnalité vous spécifiez.

Je pourrais essayer de re-cadrer le problème un peu si: que feriez-vous avec des objets que vous ne pouvez pas « traiter correctement »? Si vous êtes juste de les laisser dans la file d'attente, vous devrez les retirer à un moment donné et de les traiter. Je vous recommande soit de trouver comment les traiter (généralement, si un queue.get () donne une sorte de valeur invalide ou mauvaise, vous êtes probablement OK pour laisser tomber juste sur le sol) ou le choix d'une structure de données différente de celle une FIFO.

Pas une réponse en soi, mais: -6653412 JDK affirme ce n'est pas un cas d'utilisation valide.

La solution 'simple'

  

Ne pas traiter la suivant élément jusqu'à ce que le précédent élément est traité avec succès.

public void run() {

Object lastSuccessfullyProcessedElement = null;

    while (!exit) {
        Object obj =  lastSuccessfullyProcessedElement == null ? queue.take() : lastSuccessfullyProcessedElement; // blocking

        boolean successful = process(obj);

        if(!successful) {
            lastSuccessfullyProcessedElement = obj;
        } else {
            lastSuccessfullyProcessedElement = null;
        }
    }
}
  1. Appel peek() et vérifier si la valeur est nulle n'est pas CPU efficace.

Je l'ai vu l'utilisation du processeur va à 10% sur mon système lorsque la file d'attente est vide pour le programme suivant.

while (true) {
   Object o = queue.peek();
   if(o == null) continue;
   // omitted for the sake of brevity
}
  1. Ajout sleep() ajoute la lenteur.

  2. Ajout de nouveau à la file d'attente à l'aide putLast va perturber l'ordre. , Il est en outre une opération de blocage qui nécessite des serrures.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top