7
votes

Java- réutilisant un fil avec la même course mais différents paramètres

J'ai toujours du mal à m'envelopper la tête autour des fils et j'essaie de le faire de la manière la plus simple possible. Je sais que les threads doivent tous avoir une méthode de course, ils ont hérité de la classe annulable, mais ils peuvent avoir des méthodes supplémentaires aussi bien, corrigez-vous?

La raison étant, j'ai un fil avec des variables privées et une méthode de course. Il appelle sa fonction d'exécution et une fois que cela est fait, je veux réutiliser le fil avec la même méthode de course. Il fait exactement la même chose, juste avec différentes variables. Ainsi, j'ajouterai quelque chose comme une méthode de setarray (le thread contient un tableau d'octet privé) afin que je puisse simplement appeler simplement courir avec ce nouveau tableau ou que cela n'est pas autorisé. Je suppose que je suppose que c'est simplement, ce serait quelque chose comme xxx

essentiellement, je n'ai qu'un nombre fixe de fils et lorsque le premier thread est effectué, je veux changer Les paramètres un peu et doivent-ils courir à nouveau. Je ne les mange pas à mourir, ce qui semble être ce qui se joint à.

Pour le problème spécifique, j'ai dit 4 threads, que chacun donne un bloc de taille de jeu d'un tableau d'octet plus grand. Chaque fil comprime ce tableau avec un déflater et transmet leur résultat à un objet gestionnaire qui gère la synchronisation. Une fois le premier fil (comme dans le fil qui a obtenu la première partie du tableau, la première à finition) n'est pas terminée, il passe sur le bloc suivant non attribué à un thread.

Je sais du fil Les piscines sont une option, mais cela semble un peu surkill et je ne les comprends vraiment pas (j'ai toujours des problèmes avec juste des discussions normales).


0 commentaires

4 Réponses :


1
votes

Faites une classe distincte pour votre code qui implémente Runnable. Vous devrez faire de nouveaux objets de thread à chaque fois, mais construisez-les avec votre seul objet runnable. La méthode de course sera réutilisée par chaque thread.


0 commentaires

1
votes

Un thread commence toujours exactement une fois, fonctionne exactement une fois, puis décède exactement une fois. Donc, vous ne pouvez pas appeler Démarrer () sur le fil à plusieurs fois de la manière dont vous suggérez.

Donc, d'une manière ou d'une autre, vous devez soit:

  • avoir un seul fil qui, d'une manière ou d'une autre dans sa méthode de course (), exécute chacun de vos appels de méthode avec les différents ensembles de paramètres.
  • Démarrez un nouveau thread pour chaque "exécution" (appel de la méthode à la chose que vous voulez réellement faire).

    Quelle implémentation est plus appropriée dépend un peu sur votre application exacte. Mais en général, il est utile de penser à un fil comme une sous-tâche qui fonctionne parallèle à d'autres sous-tâches. Donc en général:

    • Si vous avez une série de "pistes" indépendantes de quelque chose que vous n'avez aucune raison de fonctionner en parallèle les uns aux autres, arrangez-vous que ces courses doivent être exécutées une après l'autre à l'intérieur d'une méthode à fil unique.Run (); < / li>
    • Si vous avez une série de tâches pouvant aussi bien fonctionner parallèlement les unes aux autres, mettez chacun dans un fil séparé.

      Un bassin de fil est généralement utilisé pour les cas où vous pouvez avoir une tâche arbitraire à exécuter, et de telles tâches peuvent exécuter en parallèle. Par exemple, sur un serveur typique. Pensez à un serveur Web recevant des demandes de pages à partir de différents clients à des moments arbitraires à temps: chaque demande peut venir à un point arbitraire à temps et qu'une demande de page d'un client est totalement indépendante d'une demande d'un autre client. En principe, vous ne vous souciez pas de quelles demandes fonctionnent parallèlement à laquelle votre machine a des contraintes de ressources telles que le nombre de processeurs. Pour ce type de cas, où vous souhaitez efficacement "exécuter des tâches arbitraires dans des threads arbitraires, jusqu'à une limite de x tâches exécutées en parallèle", vous utiliseriez généralement une piscine de fil.


2 commentaires

Je pense que mes problèmes tombent au milieu. Je veux que ces n blocs compressent en parallèle, mais dans le même temps, je ne peux pas les assigner arbitrairement car je dois conserver l'entrée et la sortie dans le même ordre (sinon si le premier fil finit en dernier, je vais avoir des données de commande). Je pense que dans mon cas, je devrai simplement les laisser mourir et commencer un nouveau fil pour chaque course.


Qu'en est-il des limitations concernant le GC? Lors de la création constante de nouveaux threads avec un exécuteur, GC jette des erreurs.



-3
votes

Les threads sont fondamentalement des objets avec l'état et une méthode à exécuter. Voici un exemple de fil: XXX

Les fils sont généralement exécutés en parallèle, sinon l'ensemble du point de filetage multi-threading est perdu. Par conséquent, nous essayons d'utiliser un pool de fils à exécuter, comme en témoigne la classe de pilotes suivante: xxx


1 commentaires

Comment cette réponse est-elle demandée par l'OP?



15
votes

Premièrement, il est préférable d'utiliser la classe Standard thread (Ne pas sous-classer!) et mettez votre code d'application dans une classe qui implémente exécutable . Cela facilite beaucoup plus facilement de séparer votre logique d'application du problème de la gestion des threads.

Deuxièmement, vous devez comprendre qu'un objet de thread appelle la méthode Exécuter une seule fois. Après la méthode est renvoyé (ou terminé par une exception), l'objet de thread est mort et ne peut pas être ramené à la vie.

Donc, si vous souhaitez "réutiliser" les instances , vous devez organiser que la méthode exécuter est une boucle qui attend que la prochaine chose à être Fini. Et avant de savoir que vous êtes implémenter un piscine de thread.

Il y a une autre alternative (plus "moderne") à une piscine de fil. Créez un ExecuTorservice instance et utilisez la méthode Soumettre () pour soumettre les instances exécubles pour exécution. L'interface Javadoc possède un bon exemple d'utilisation, à l'aide d'une instance de service exécutant avec une piscine privée. Si vous le souhaitez, vous pourrait réutiliser les instances exécubles , mais il est généralement plus simple (et plus sûr) de créer de nouveaux à chaque fois.


5 commentaires

Vous avez d'abord dit - N'abandonnez pas la sous-classe, mais à la fin, vous dites qu'il plus simple de créer une nouvelle instance à chaque fois. Comment faire une instance d'un fil si non en mettant en œuvre le fil dans une sous-classe?


@somefolk - Lisez-la à nouveau. Il devrait être clair du contexte que je parle de nouvelles instances de runnable . (Évident, ils seront des cas de classe qui implémente runnable ... "parce que vous ne pouvez pas créer une instance d'interface.)


Qu'en est-il des limitations concernant le GC? Lors de la création constante de nouveaux threads avec un exécuteur, GC jette des erreurs.


@ ylun.ca - Vous devriez utiliser un exécuteur exécutant avec un bassin de fil borné. Le problème de GC ne provient que si l'exécuteur crée trop de threads.


Quelque chose d'autre que j'aurais dû mentionner sur le commentaire ci-dessus est que le GC n'est impliqué dans aucun de cela. L'Oome Vous obtenez lorsque vous ne pouvez pas lancer un thread est lancé par thread :: start () , et il arrive généralement quand il y a trop de threads en direct et que la JVM ne peut pas allouer une pile. Mais l'espace de pile est séparé du tas et les piles de fil ne sont pas gérées par le GC. (En effet, le GC ne récupérera pas un fil pendant qu'il est toujours en vie ... Même si l'objet n'est pas accessible à partir du code de l'application.)