Question

Je me demande s'il est coûteux d'avoir plusieurs threads en attente dans Java 1.6 x64.

Pour être plus précis, j'écris une application qui fonctionne sur plusieurs ordinateurs et envoie / reçoit des données de l'un à l'autre. Je me sens plus à l'aise d'avoir un thread séparé pour chaque machine et tâche connectées, comme 1) l'envoi de données, 2) la réception de données, 3) le rétablissement de la connexion lorsqu'elle est abandonnée. Donc, étant donné qu'il y a N nœuds dans le cluster, chaque machine va avoir 3 threads pour chacun des N-1 voisins. En règle générale, il y aura 12 machines, ce qui correspond à 33 tâches de communication.

La plupart de ces threads seront en veille la plupart du temps. Par conséquent, je pourrais réduire le nombre de threads et leur attribuer plus de travail. Comme par exemple. rétablir la connexion est la responsabilité de recevoir le fil. L’envoi à toutes les machines connectées se fait par un seul thread.

Existe-t-il un impact significatif sur les performances de nombreux fils en sommeil?

Était-ce utile?

La solution

Dans la plupart des cas, les ressources consommées par un thread en veille sont son espace de pile. Utiliser un modèle à 2 threads par connexion, qui, je pense, est similaire à ce que vous décrivez, est connu pour causer de gros problèmes d’évolutivité pour cette raison même lorsque le nombre de connexions augmente.

Je suis moi-même dans cette situation et lorsque le nombre de connexions dépasse 500 connexions (environ 1 000 threads), vous avez tendance à entrer dans de nombreux cas où vous obtenez OutOfMemoryError, car l'utilisation de l'espace de pile des threads dépasse la quantité maximale de mémoire pour un processus unique. Au moins dans notre cas, qui était dans un monde Java sous Windows 32 bits. Vous pouvez ajuster les choses et aller un peu plus loin, je suppose, mais au final, ce n'est tout simplement pas très évolutif, car vous perdez beaucoup de mémoire.

Si vous avez besoin d'un grand nombre de connexions, Java NIO (nouvel IO ou autre) est la solution, permettant de gérer de nombreuses connexions dans le même thread.

Ceci étant dit, vous ne devriez pas rencontrer trop de problèmes avec moins de 100 threads sur un serveur raisonnablement moderne, même s'il s'agit probablement encore d'un gaspillage de ressources.

Autres conseils

Nous avions à peu près le même problème avant de passer à NIO. Je vais donc appuyer la recommandation de Liedmans de s’inscrire dans ce cadre. Vous devriez pouvoir trouver un didacticiel, mais si vous souhaitez en savoir plus, je vous recommanderais Java. NIO de Ron Hitchens.

Le passage à NIO a augmenté le nombre de connexions que nous pouvions gérer beaucoup, ce qui était vraiment essentiel pour nous.

Cela ne sera pas très bon. Avoir un grand nombre de threads signifie que la VM doit passer plus de temps à la commutation de contexte, et l'utilisation de la mémoire sera plus grande du fait que chaque thread nécessite son propre espace de pile. Vous feriez mieux de traiter un nombre inférieur de threads en mode pipeline ou d’utiliser le pool de threads avec des techniques asynchrones.

Beaucoup de threads équivalent à beaucoup d'espace de pile, ce qui grignotera votre mémoire - vérifiez vos paramètres -Xss pour combien, puis faites le calcul.

Et si vous devez faire un notifyAll () pour quelque raison que ce soit, alors vous réveillez des tonnes de threads supplémentaires, bien que vous n'ayez peut-être pas besoin de le faire dans votre architecture proposée.

Je ne suis pas sûr que vous puissiez facilement éviter d'avoir un seul thread par socket d'écoute dans ce modèle (bien que je sache très peu de choses sur NIO - ce qui pourrait même résoudre ce problème), mais jetez un coup d'œil à la java.util.concurrent.Executor et ses classes d'implémentation pour une façon décente d'éviter d'avoir trop de fils supplémentaires traîner. En effet, ThreadPoolExecutor peut également être un bon moyen de gérer vos threads d'écoute, afin que vous ne perdiez pas trop de temps à créer et à détruire des threads de manière inutile.

D'après les tests que j'ai effectués en C, Lua et Python, vous pouvez créer votre propre fonction de veille ou d'attente avec de très petites lignes de codes pour créer une simple boucle légère. Utilisez une variable locale avec l'heure future que vous souhaitez atteindre, puis testez l'horodatage actuel dans une boucle while. Si vous travaillez dans une étendue où vous travaillez avec fps, faites en sorte que la fonction attente soit exécutée une fois par image pour économiser les ressources. Plus vous avez besoin de précision, envisagez d'utiliser l'horloge au lieu de l'horodatage, car l'horodatage est limité à quelques secondes. Plus vous ajoutez de lignes de code dans une fonction d'attente, moins elle devient précise et plus elle consomme de ressources, même si toute ligne inférieure à 10 lignes devrait être assez rapide.

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