IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

La bonne méthode pour faire des timers


Sujet :

Java

  1. #1
    Membre du Club Avatar de Tigrounette
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 132
    Points : 69
    Points
    69
    Par défaut La bonne méthode pour faire des timers
    Bonjour à tous, je vous explique mon problème :

    J'ai un petit jeu multijoueur dans lequel les joueurs peuvent poser des bombes qui explosent au bout d'un certain temps (Un bomberman). Le moment ou les bombes explosent sont donc gérés par le serveur (qui est en java).

    Le problème, c'est quand il y a trop de monde, donc quand plusieurs centaines de joueurs posent leurs bombes en même temps, le serveur commence à m'envoyer cette erreur : java.lang.OutOfMemoryError: unable to create new native thread, pour finir par ne plus réagir. Le reste des informations d'indique que c'est en voulant ajouter une nouvelle bombe qu'il plante.

    Pour créer une bombe côté serveur, j'utilise cette classe (j'ai simplifié un peu pour garder l'essentiel) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    public class Bombe extends Thread {
    	private int Temps;
    	private boolean Active = true;
     
    	private Bombe(int TEMPS) {
    		Temps = TEMPS;
    		start();
    	}
     
    	public void run() {
    		try {
    			sleep(Temps);
    			if (Active) {
    				Explosion();
    			}
    		} catch (Exception e) {
    		}
    	}
    }
    Mais apparement c'est une mauvaise méthode

    J'aimerais donc connaitre la bonne méthode pour retarder l'execution d'une fonction d'un certain temps. L'objectif étant de pourvoir en faire plusieurs centaines simultanément ^^

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Salut,



    Si tu génères un grand nombre de thread au même moment ce problème est tout à fait normal. Les threads sont des ressources systèmes critiques et il ne faut pas en abuser.

    Dans ton cas la meilleur solution serait de passer par un thread unique qui gèrerait toutes les explosions. Cela peut se faire tout simplement en utilisant la classe Timer et sa méthode shedule() pour planifier un événement à un instant donné...


    a++

  3. #3
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Dans leur présentation de JavaOne 2008, Gfx et Chet se sont justement penchés sur le problème de multiples Timer (dans leur cas dans une GUI Swing et donc avec le Timer Swing plutôt que celui de java.util). Ils indiquent bien qu'avoir trop de Timer est un gène car alors cela pompe trop de ressources et on obtient l'effet inverse de celui recherché.

    Leur solution consiste donc en un Timer unique à faible résolution et des évènements qui sont stockés dans un arbre/graphe. Si je ne m'abuse (et si je n'ai pas tout mélangé ) s'est plus ou moins inspiré/dérivé de GraphScene pour JavaFX (à moins que ce ne soit l'inverse). Bref, il est possible que tu doives t'inspirer d'une telle solution (leur présentation est disponible en session audio sur le site de JavaOne ou en PDF sur le site de Gfx - http://www.curious-creature.org/2008...-javaone-2008/). Bien sur il faudra t'arranger pour que les événements lancés par le Timer s'exécutent de manière asynchrone histoire de ne pas ralentir le Timer lui-même.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  4. #4
    Membre du Club Avatar de Tigrounette
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 132
    Points : 69
    Points
    69
    Par défaut
    Bon, après quelques test je reviens vers vous.

    j'ai utilisé la méthode de bouye. J'ai une boucle dans un thread à part qui vérifie toutes les 50 millisecondes si une bombe doit exploser ou non (si c'est bien cette méthode).

    Alors ça va un peu mieux, mais le serveur plante vers 300 peronnes au lieu de 200, donc c'est pas encore trop ça.

    Bref, a part le thread de chaque client, j'en ai pas de masse non plus. 2 thread par partie pour gérer le chronomètre et parfois quelques autres pour gérer différentes choses.

    En gros, le serveur dois planter quand environ 500-600 thread sont actif en même temps et refuse d'en créer d'autre avec toujours le même message d'erreur : java.lang.OutOfMemoryError: unable to create new native thread.

    Le problème, c'est que je regarde un peu ce qui se passe niveau mémoire à ce moment là et je me rend compte que le programme java m'indique qu'il utilise environ 60 mo pour 508 mo de libre

    C'est un peu énervant comme bug, j'ai tenté de me renseigner sur cette erreur mais j'ai pas trouvé grand chose. Ya t'il une manipulation à faire pour autoriser une application java à créer autant de thread qu'elle veut ? Au niveau de la compilation ou du système d'exploitation ?

  5. #5
    Rédacteur/Modérateur

    Avatar de bouye
    Homme Profil pro
    Information Technologies Specialist (Scientific Computing)
    Inscrit en
    Août 2005
    Messages
    6 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Nouvelle-Calédonie

    Informations professionnelles :
    Activité : Information Technologies Specialist (Scientific Computing)
    Secteur : Agroalimentaire - Agriculture

    Informations forums :
    Inscription : Août 2005
    Messages : 6 840
    Points : 22 854
    Points
    22 854
    Billets dans le blog
    51
    Par défaut
    Quelle JVM ? Quel OS ? Quel vendeur ? As-tu utilise un flag -Xmx<kekchose> particulier pour augmenter la taille de la memoire utilisable ?

    De toute maniere tu seras toujours limite, y compris par l'OS : on ne peut pas creer une infinite de Thread. Pour des tres grosses quantites tu devras utiliser des Thread pools et faire du scheduling.
    Merci de penser au tag quand une réponse a été apportée à votre question. Aucune réponse ne sera donnée à des messages privés portant sur des questions d'ordre technique. Les forums sont là pour que vous y postiez publiquement vos problèmes.

    suivez mon blog sur Développez.

    Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to produce bigger and better idiots. So far, the universe is winning. ~ Rich Cook

  6. #6
    Modérateur
    Avatar de nouknouk
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    1 655
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 655
    Points : 2 161
    Points
    2 161
    Par défaut
    salut,

    Bref, a part le thread de chaque client
    Pour ce point précis, j'imagine que tu parles du serveur et donc du thread rattaché à la socket client pour faire le 'read()' bloquant.

    Au lieu de faire un thread par socket client, tu peux utiliser l'API Java NIO pour n'avoir qu'un seul thread pour toutes les socket clientes.

    En gros, le principe de l'API NIO est d'avoir un seul appel bloquant sur un 'selector' qui sera débloqué dès qu'une socket parmi toutes celles enregistrées dans le 'selector' aura reçu quelque chose (ou se sera déconnectée).

    Le moment ou les bombes explosent sont donc gérés par le serveur
    Peut-être que pour ça tu peux utiliser une approche différente (idée saugrenue, mais bon): que ce soit un des joueurs de la partie (celui à qui l'explosion profite le moins) qui prévienne lorsqu'une bombe a explosé en envoyant le message au serveur. Le serveur n'aura alors plus qu'à vérifier que le client dit vrai et qu'à ce moment là la bombe aurait bien du exploser, et faire le traitement en conséquence a postériori.
    Mon projet du moment: BounceBox, un jeu multijoueurs sur Freebox, sur PC et depuis peu sur smartphone/tablette Android.

  7. #7
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Tigrounette Voir le message
    Bref, a part le thread de chaque client, j'en ai pas de masse non plus. 2 thread par partie pour gérer le chronomètre et parfois quelques autres pour gérer différentes choses.

    En gros, le serveur dois planter quand environ 500-600 thread sont actif en même temps et refuse d'en créer d'autre avec toujours le même message d'erreur : java.lang.OutOfMemoryError: unable to create new native thread.

    Le problème, c'est que je regarde un peu ce qui se passe niveau mémoire à ce moment là et je me rend compte que le programme java m'indique qu'il utilise environ 60 mo pour 508 mo de libre
    Ce n'est pas un problème de mémoire, mais tout simplement l'impossibilité de créer de nouveau thread...

    D'après ce que tu dis (300 joueurs, 500-600 threads), on dirait que tu arrives à utiliser 2 threads/joueurs. C'est peut-être un peu beaucoup.

    Les systèmes d'exploitations ont des limites au nombre de thread par processus, et tu dois atteindre ces limites.

    Si tu utilises seulement des threads pour les données clientes, NIO pourrait en effet être la solution...

    a++

  8. #8
    Membre du Club Avatar de Tigrounette
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 132
    Points : 69
    Points
    69
    Par défaut
    Je commence à comprendre tous ça un peu mieux. Pour moi, faire des thread dans tous les sens était une bonne manière de faire C'est vrai qu'en y réfléchissant, je pourrais utiliser 3-4 thread pour gérer tous ce qui n'est pas thread client et tenter d'utiliser java.nio pour les clients.

    Je suis en train de tout casser pour utiliser java.nio, je vous tiens au courant

  9. #9
    Modérateur
    Avatar de nouknouk
    Homme Profil pro
    Inscrit en
    Décembre 2006
    Messages
    1 655
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France

    Informations forums :
    Inscription : Décembre 2006
    Messages : 1 655
    Points : 2 161
    Points
    2 161
    Par défaut
    Citation Envoyé par Tigrounette Voir le message
    Je suis en train de tout casser pour utiliser java.nio, je vous tiens au courant
    Un petit lien avec des explications claires (en Anglais) et du code ... si tu n'as pas déjà trouvé mieux
    Mon projet du moment: BounceBox, un jeu multijoueurs sur Freebox, sur PC et depuis peu sur smartphone/tablette Android.

  10. #10
    Membre du Club Avatar de Tigrounette
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 132
    Points : 69
    Points
    69
    Par défaut
    Bon, c'est encore moi mais avec un autre problème.

    J'ai un truc qui fonctionne en local sur mon pc windows qui utilise java.nio.

    Le problème, c'est lorsque je met tous ça sur mon serveur linux, je me retrouve avec cette erreur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Exception in thread "main" java.lang.InternalError: unable to get address of epoll functions, pre-2.6 kernel?
            at sun.nio.ch.EPollArrayWrapper.init(Native Method)
            at sun.nio.ch.EPollArrayWrapper.<clinit>(EPollArrayWrapper.java:258)
            at sun.nio.ch.EPollSelectorImpl.<init>(EPollSelectorImpl.java:52)
            at sun.nio.ch.EPollSelectorProvider.openSelector(EPollSelectorProvider.java:18)
            at Nio.initSelector(Nio.java:199)
            at Nio.<init>(Nio.java:42)
            at Serveur.main(Serveur.java:103)
    Ca coince sur cette ligne de code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Selector socketSelector = SelectorProvider.provider().openSelector();
    Avec le SelectorProvider importé :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    import java.nio.channels.spi.SelectorProvider;
    Là, je me dit que ça viens de linux et je ne sais absolument pas comment régler le problème, sachant que linux, j'y connais à peu près rien. J'ai cherché un peu sur google mais je comprend rien aux explications ^^

    J'ai essayé de compiler directement sur mon serveur, la compilation fonctionne mais j'ai la même erreur

    Ya t'il un moyen simple de régler le problème en faisant un réglage sur mon linux ou en modifiant mon code (enfin, sans utiliser SelectorProvider) ?

  11. #11
    Membre du Club Avatar de Tigrounette
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 132
    Points : 69
    Points
    69
    Par défaut
    Bon ben, j'ai réglé le problème en ajoutant ce paramètre au moment de lancer le serveur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    -Djava.nio.channels.spi.SelectorProvider=sun.nio.ch.PollSelectorProvider
    Je sais pas ce que ça fait exactement, mais ça marche

    Je met pas encore le Résolu, j'attend de voir si j'arrive à dépasser 300 joueurs

    (si vous voulez m'y aider : Venez par ici )

Discussions similaires

  1. [WD20] Le choix de la bonne méthode pour filtrer des données
    Par lololebricoleur dans le forum WinDev
    Réponses: 3
    Dernier message: 20/02/2015, 21h04
  2. Bonne méthode pour faire un formulaire ?
    Par tiesto95 dans le forum Balisage (X)HTML et validation W3C
    Réponses: 5
    Dernier message: 15/03/2009, 18h16
  3. une bonne librairie pour faire des log ?
    Par lezurp dans le forum C++
    Réponses: 12
    Dernier message: 02/03/2009, 14h10
  4. Réponses: 5
    Dernier message: 23/04/2008, 15h41
  5. Meilleure méthode pour faire des coins arrondis
    Par kodokan dans le forum Balisage (X)HTML et validation W3C
    Réponses: 1
    Dernier message: 17/09/2006, 15h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo