2011-11-18 6 views
2

Je me suis retrouvé à penser à la résolution d'un problème de simultanéité, ce qui pour moi indique qu'il y a probablement une abstraction pour accomplir ce que je veux que je devrais utiliser à la place.Java Abstraction Abstraction for Work Queue

Voici la prémisse de base:

  • J'ai une file d'attente de données que je peux faire le travail sur
  • threads peuvent venir et ajouter du travail à la file d'attente
  • Il y a une surcharge élevée associée avec départ et arrivée d'un ensemble d'éléments à travailler sur
  • un seul thread peut travailler sur les données à la fois

je me suis dit l'API suivante serait bien:

  • Threads peuvent ajouter du travail à la file d'attente
  • Si les données de la file d'attente ne sont pas actuellement en cours d'élaboration, invoquez une tâche de fond pour commencer à travailler
  • La tâche de fond continue à travailler sur la file d'attente jusqu'à ce qu'il soit vide, même si d'autres threads déposer des éléments supplémentaires pour travailler dans la file d'attente

la partie difficile est de garantir que les données ne siège pas dans la file d'attente ne sont pas travaillé dans le événement qu'un fil tombe d'un travail en même temps que le fil de travail est en train de finir.

Je suppose qu'il existe une abstraction pour résoudre ce problème. Quelqu'un en sait-il?


Edit:

Pour être plus précis, je parle d'une recherche incrémentale indexeur, et les données ajouté à la file d'attente est des documents supplémentaires à traiter. Quand je parle de démarrer et d'arrêter un groupe de travail, je fais référence à la construction d'un contexte de mise en cache et à la mise à jour d'un index. Nous ne pouvons pas exécuter un thread de travail à tout moment, car si nous ne validons jamais, le nouvel index ne sera jamais validé, et si nous ne fermons pas le contexte de mise en cache périodiquement, il peut devenir trop grand. Le but est que la plupart du temps, seulement quelques travaux sont traités à la fois, mais pendant les périodes de forte charge, nous ne perdons pas trop de temps à faire trop de commits.

+0

Il y a donc un surcoût élevé à démarrer et à arrêter, mais vous pouvez ajouter à l'exécution en cours sans frais supplémentaires? Alors, n'arrêtez jamais votre course! :-D Mettez un occupé-attendez là, comme 'Thread.sleep (500);' peut-être. – corsiKa

Répondre

1
+3

vous devez utiliser une file d'attente de blocage. En fait, un thread essayant de lire depuis cette file bloquera jusqu'à ce qu'un autre thread y mette quelque chose. Voir le lien que j'ai fourni dans ma réponse pour l'api et le javadoc. Je recommande également, en lisant "Java: Concurrency in Practice" par Brian Goetz –

0

Vous pouvez consulter la Disruptor, un projet open source qui est tout au sujet du traitement d'un beaucoup de données avec très faible latence, pour , séquentiellement. Je ne l'ai pas utilisé, personnellement, mais cela semble juste pour votre problème.

+0

Il semble que vous ayez besoin de réécrire complètement votre code pour utiliser ce framework, donc ce n'est utile que si vous avez vraiment besoin de vitesse. – toto2

+0

Oui, AFAIK c'est une abstraction totalement différente d'une file d'attente. Je ne pense pas que le cas d'utilisation réel de cette question ait été inclus lorsque j'ai écrit la réponse, et cela ne semble pas être une faible latence ou une performance optimale. – Grundlefleck

1

"Un seul thread peut fonctionner sur les données à la fois" - Cette ligne indique que vous avez besoin d'un sémaphore pour contrôler le nombre de travailleurs (consommateurs) qui peuvent travailler.

Pour le côté producteur, vous aurez besoin d'une file d'attente de blocage afin que le producteur bloque (attendez) si la liste est pleine avant de l'ajouter à la liste.