2010-12-30 4 views
4

J'ai un composant Java qui exécute une logique métier super compliquée, dont certains sont mis en parallèle et les sous-tâches exécutant des threads sont regroupées. Maintenant, chaque requête à ce composant peut avoir une certaine priorité qui est mappée d'une certaine manière à la priorité des threads. A le début de l'exécution je peux assigner une priorité appropriée à l'exécution du thread. La partie problématique est de passer la priorité à chaque thread exécutant des sous-tâches. Je sais que la création d'un nouveau thread enfant permettra d'accomplir cela car les threads fils héritent de la priorité des threads parents, mais je voudrais profiter du pool de threads. Une question:Passage de priorités de threads aux pools de threads

  • Y at-il un moyen de s'assurer que chaque thread dans le chemin d'exécution a la priorité appropriée?
  • Comment puis-je surveiller la priorité des threads à chaque étape de l'exécution, bien sûr je ne veux pas coder en dur n'importe quel code de traçage? Sur la chose qui est venu dans mon esprit est d'écrire un script de suivi dans BTrace

Cheers. Tomek

Répondre

3

En ce qui concerne la mise en priorité du thread est concerné, vous pouvez utiliser les différentes méthodes de la classe Executors qui prennent ThreadFactory. Cette usine serait responsable de la création de threads basés sur le passé dans "Runnable". En ce qui concerne la surveillance, pouvez-vous extrapoler sur le scénario que vous essayez d'aborder ici lorsque vous dites «chaque étape d'exécution»? Comme il a été ailleurs mentioned, puisqu'il n'y a pas un mappage clair entre les priorités de thread Java et OS, se fier à ces priorités serait une mauvaise chose, dans le cas où vous essayez ici.

3

Je suppose que vous le savez déjà, mais que la valeur de priorité de JDK Thread soit importante ou non est très spécifique au système d'exploitation et peut se traduire par "n'a aucun effet". Alors êtes-vous sûr que cela compte réellement? Si c'est le cas, modifiez peut-être la question pour indiquer que le système d'exploitation fonctionne.

En outre: il n'est pas très courant d'essayer même d'utiliser les priorités de threads; En plus des priorités qui ne fonctionnent pas nécessairement, il n'est pas trivial d'en faire bon usage même si elles fonctionnent. Plus communément, les primitives de synchronisation sont utilisées, ainsi que le contrôle du niveau de concurrence (nombre de threads actifs), pas de priorités. Ceci parce qu'il y a rarement des avantages à avoir plus de threads liés au CPU actifs que de systèmes de cœurs.

+0

Je sais que la mise en œuvre des priorités est un très OS/machine virtuelle Java pense spécifique, mais mon travail composante que sur les fenêtres et les priorités semblent fonctionner très bien là-bas . De plus, je ne construis pas un composant à partir de rien, mais seulement brancher des priorités sur une chose existante. Vous avez mentionné les primitives de synchronisation. Pourriez-vous préciser comment utiliser cette approche pour classer par ordre de priorité 1 000 demandes parallèles sans les priver de la priorité la plus basse? – Tomek

+0

Requêtes Wrk 1k; dépend. Si elles sont en grande partie en attente d'E/S, l'utilisation de NIO (solution basée sur) aurait du sens - 1000 threads ou plus peuvent être un modèle très inefficace. Si lié à l'UC, eh bien, vous ne devriez jamais commencer à traiter autant de requêtes simultanées, mais commencer à échouer plus tôt. Donc, ce que je veux dire est ce nombre limite de threads réels par la mise en file d'attente, en commençant à échouer tôt, etc: les threads ne peuvent pas résoudre la situation de surcharge. Mais si vous pensez que les priorités de threads sont utiles, et qu'elles fonctionnent sur la plate-forme (ce que vous avez probablement raison à propos de Windows), alors rien de mal à utiliser. Juste cela assurez-vous qu'ils aident. – StaxMan

1

Cela pourrait résoudre votre problème: Thread.currentThread(). SetPriority ([1..5]);

Vous pouvez les utiliser de n'importe où. Si vous les utilisez depuis un runnable lancé par un pool de threads, vous pouvez contrôler la priorité de thread unique et la modifier si nécessaire.

4

Vous souhaitez utiliser des pools de threads, ce qui serait inutile si vous deviez générer de nouveaux threads uniquement pour définir la priorité du travail.

Je pense que vous voulez que chaque emploi (non fil) d'avoir une autre priorité. Si tel est le cas, nous allons regarder une signature du constructeur pour ThreadPoolExecutor:

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, 
TimeUnit unit, BlockingQueue<Runnable> workQueue) 
  • Au lieu d'utiliser l'un des Executors recommandés "méthodes d'usine pour construire votre pool de threads, faire new ThreadPoolExecutor(...) vous, en utilisant l'un de ses nombreux signatures.
  • Passez le Executors.defaultThreadFactory dans ce constructeur (la signature que j'ai listée ci-dessus le fait en interne). Cela fera automatique thread attribution de priorité car il crée les threads (pour un pool de threads de taille fixe, qui devrait se produire une seule fois par thread, au démarrage de l'application).
  • Passez un BlockingQueue<Runnable> ou PriorityBlockingQueue<Runnable> dans ce constructeur. C'est la file d'attente qui vous permettra de donner la priorité emplois (pas threads).
  • Étendre Runnable dans une classe abstraite PriorityRunnable qui permet d'obtenir/définir la priorité. Ceux-ci représentent les emplois, donc quand vous voulez faire un nouveau travail, étendez simplement cela et personnalisez la priorité comme approprié pour ce travail.
  • Implémentez Comparator pour effectuer une commande sur les éléments lorsque vous les insérez dans la file d'attente et laissez cette file d'attente l'utiliser.
  • Ajoutez vos travaux à la file d'attente.

Notez que si vous avez votre file d'attente déjà peuplée par cette fois-ci (par exemple. Pour les applications de traitement par lots), vous pouvez appeler executor.prestartAllCoreThreads() ou executor.prestartCoreThread(n) à la fois après la construction.

Tout est très simple, et prend étonnamment peu de lignes de code à configurer.

EDIT: Je viens de trouver la même approche en cours de discussion over at Java Ranch.

2

Je l'ai récemment implémenté. Je l'ai fait beaucoup comme Nick Wiggill l'a suggéré. Mais vous ne pouvez pas simplement faire ce qu'il a suggéré, car ThreadPoolExecutor ne place pas les travaux que vous avez demandés dans la file d'attente de travail - à la place, il les enveloppe dans son propre RunnableFuture et les place dans la file d'attente. Vous devez donc remplacer sa méthode newTaskFor pour transmettre la priorité.

Le code source est en ligne sous la licence Apache 2.0: https://github.com/TheClimateCorporation/claypoole/blob/master/src/java/com/climate/claypoole/impl/PriorityThreadpoolImpl.java