2

J'ai 3 classes de tâche (I, D, U) qui entrent dans une file d'attente, les tâches de la même classe doivent être traitées dans l'ordre. Je veux que les tâches s'exécutent aussi simultanément que possible; mais il y a des contraintes:modèle de conception pour l'exécution simultanée de tâches avec des contraintes

  • U et D ne peuvent pas fonctionner en même temps
  • U et je ne peux pas exécuter simultanément
  • I (n) nécessite U (n) a terminé

Q: Quel (s) motif (s) de conception correspondraient à cette catégorie de problème?

J'ai deux approches j'envisage:

Approche 1: Utiliser 1 fil par tâche, chacun avec sa propre file d'attente. Chaque thread a une phase de démarrage synchronisée où il vérifie les conditions de démarrage, puis s'exécute, puis une phase d'arrêt synchronisée. Il est facile de voir que cela fournira une bonne simultanéité, mais je ne suis pas sûr si elle implémente correctement mes contraintes et ne se bloque pas.

D_Thread { ... 
while (task = D_Queue.take()) { 
    synchronized (State) { // start phase 
    waitForU(); 
    State.setRunning(D, true); 
    } 
    run(task); // run phase 
    synchronized (State) { // stop phase 
    State.setRunning(D, false) 
    } 
} 
} 

Approche 2: Alternativement, un seul thread d'expédition gère l'état d'exécution et tâches horaires dans un ThreadPool, en attendant si nécessaire pour des tâches actuellement prévues pour terminer.

+0

Pourriez-vous parler plus en détail troisième contrainte? Est-ce que I et U viennent par paires et que chacun d'eux requiert son U apparié, ou il n'y a pas de telles paires, mais simplement le nombre de I complétés ne peut pas être supérieur au nombre de U complétés? Ou autre chose? – Dialecticus

+0

2) Quel est le coût en temps pour chaque catégorie de tâches? Est-ce qu'ils prennent environ le même temps pour terminer? – Dialecticus

+0

Un peu des deux. U (n) est une sorte de vidage de cache, il implique U (n-1) U (n-2) ... et ainsi de suite; Il est donc possible de traiter plusieurs à la fois. Chaque opération a une position associée à elle; D (k) crée donc une exigence pour U (k). Ils ont été conçus comme des exemples; Je ne demande pas aux gens de résoudre complètement ce problème; recommande juste quelques modèles de conception. – Justin

Répondre

1

L'infrastructure Objective-C Foundation comprend les classes NSOperationQueue et NSOperation qui répondent à certaines de ces exigences. NSOperationQueue représente une file d'attente de NSOperation s. La file d'attente exécute un nombre maximal configurable d'opérations simultanément. Les opérations ont une priorité et un ensemble de dépendances; toutes les opérations dont dépend une opération doivent être terminées avant que la file d'attente ne commence à exécuter l'opération. Les opérations sont planifiées pour s'exécuter sur un pool de threads de taille dynamique.

Qu'est-ce que vous avez besoin nécessite une version un peu plus intelligent de NSOperationQueue qui applique les contraintes que vous avez exprimées, mais NSOperationQueue et société fournissent un exemple de la façon dont à peu près votre problème a été résolu dans un cadre de production qui ressemble à votre deuxième solution proposée d'une dépêche thread exécute des tâches sur un pool de threads.

+0

Il semble que NSOperationQueue utilise un graphe orienté acyclique de dépendances et un pool de threads borné pour planifier tout ce qui n'est pas en attente d'un autre résultat. – Justin

+0

Je ne voyais pas comment exprimer mes contraintes en termes de dépendances directes. – Justin

+0

Je vais le prendre, cela ne résout pas le problème mais c'est ce que j'ai demandé. – Justin

0

En fait, cela se révèle être plus simple que cela semblait: un mutex est surtout tout ce qui est nécessaire:

IThread(int k) { 
synchronized (u_mutex) { 
    if (previousUSet.contains(k))) U(k); 
} 
I(k); 
} 

DThread(int k) { 
synchronized (u_mutex) { 
    D(k); 
    previousUSet.add(k); 
} 
}