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

avec Java Discussion :

Problème sur le pattern Singleton


Sujet :

avec Java

  1. #1
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Octobre 2016
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2016
    Messages : 19
    Points : 11
    Points
    11
    Par défaut Problème sur le pattern Singleton
    Salut

    Je m'intéresse au pattern singleton (pour obtenir seulement une instance de classe) et j'ai dû mal à comprendre son fonctionnement :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public class Singleton {
    	private static Singleton instance;
     
    	private Singleton() {}
     
    	public Singleton getInstance() {
    		if (instance == null) {
    			instance = new Singleton();
    		}
    		return instance;
    	}
    }
    Ce qui me pose problème : j'ai bien compris le principe de la méthode avec le test pour s'assurer de l'unicité de l'instance mais la variable instance de type Singleton est de type static.
    Du coup même si l'on créée plusieurs instances (en enlevant le test if == null), cela ne devrait rien changer puisque vu que la variable instance est de type static, c'est donc une variable de classe, c'est à dire qu'elle est partagée par toutes les instances.
    Donc au final, ça ne devrait rien changer si l'on enlève le if (instance == null), non ?

    Merci

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Ce que tu montres déjà, c'est un singleton dit lazy : on ne l'instancie que la première fois qu'il est demandé. On peut plus simplement le créé une fois pour toute, surtout s'il n'est pas contextualisé par un paramétrage en amont, et peu lourd. On utilisera un singleton lazy lorsque sa création est lourde (lente par exemple et donc risquant d'introduire un temps d'attente au démarrage de l'application, ou lourde pour la mémoire) : si le singleton n'est pas utilisé pendant l'exécution, on économise du temps et de la mémoire.

    Le principe d'un singleton, c'est que toutes les méthodes ou classes qui l'utilisent aient la même et unique instance (au cours d'une session d'exécution bien sûr). Or si tu supprimes le test, que va-t-il se passer ? A chaque appel de getInstance() on aura une nouvelle instance de créée. Elle a aura beau être stockée dans une variable statique, les x codes qui auront appelé la méthode getInstance() auront une instance différente : on n'aura donc plus du tout un singleton.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Singleton s1 = Singleton.getInstance();
    Singleton s2 = Singleton.getInstance();
    System.out.println( s1==s2 );
    affichera toujours false. Alors que le but c'est que cela soit toujours vrai.

    A noter que le code que tu montres n'est pas protégé contre l'accès multi-process. Si deux threads appellent la méthode getInstance() alors que l'instance est null, ils risquent fortement d'obtenir 2 instances différentes. Il faut donc synchroniser les appels au moins, voire mettre en place un système de verrou qui pénalise le moins possible l'accès au singleton lorsque celui-ci a déjà été créé (cas dans lequel il n'est plus nécessaire de synchroniser). Il existe une façon de faire un singleton non lazy qui soit thread-safe en utilisant une enum.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Octobre 2016
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2016
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    OK cool merci, ça me semble bien plus clair.
    Du moins si je résume, on pourrait dire :
    si on enlève le "if singleton = null", à chaque instant t, on a toujours une et une seule instance (du fait que ce soit une variable de classe) mais ce n'est pas forcément la même instance au cours du temps (du moins lorsqu'on utilise la méthode getInstance() ), c'est bien ça ?

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    L'instance référencée par la variable static instance est elle bien unique (ou null) à un instant t. Mais le problème c'est que ce n'est pas cette référence qu'on utilise (la variable est private). Celle qu'on utilise, c'est celle retournée par la méthode getInstance(). Et, en plus, il ne faut pas raisonner en terme d'instant t, mais en terme de process qui utilise, process qui doivent tous avoir la même unique instance quel que soit le moment où ils demandent l'instance de singleton, et aussi quelque soit le nombre de fois qu'ils appellent la méthode.
    Sans le test, si deux process successifs appellent getInstance(), tu auras 2 exécutions de new Singleton(), donc 2 instances, forcément. Que ça s'exécute à 2 minutes d'intervalles, ou 1 nanoseconde. Au final , la variable static instance n'en stockera qu'une des deux... mais ça ne change rien aux process qui continuent de s'exécuter par ailleurs avec chacun leur instance obtenue en retour de getInstance() (qui, dans le cas de process concurrents, pourrait être par accident (ou chance appelle ça comme tu veux) les mêmes aussi).
    Avec le test, tout ce qu'on garanti, c'est que pour deux process concurrents, c'est que si le process 2 fait le test lorsque le process 1 a fini d'exécuter le new Singleton() et que la référence alors créée a bien été stockée dans la variable static instance, et qu'en plus tous les caches internes auront été synchronisés, alors le process 2 aura bien de façon sûr la même instance. Le synchronize contourne le problème en disant au process 2 de ne commencer à exécuter getInstance() que lorsque le process 1 étant en train de l'exécuter a bien terminé complètement.
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  5. #5
    Membre à l'essai
    Homme Profil pro
    Enseignant
    Inscrit en
    Octobre 2016
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Enseignant
    Secteur : Enseignement

    Informations forums :
    Inscription : Octobre 2016
    Messages : 19
    Points : 11
    Points
    11
    Par défaut
    Arf merci de ton explication mais j'avoue que ça reste confus pour moi, du moins ça m'apporte de nouvelles interrogations :
    "L'instance référencée par la variable static instance est elle bien unique (ou null) à un instant t. Mais le problème c'est que ce n'est pas cette référence qu'on utilise (la variable est private). "

    Pourtant dans la méthode getInstance() il y a un return instance : du coup lorsqu'on fait Singleton s1 = Singleton.getInstance(), cela signifie pour moi que s1 et instance (qui est private) sont deux références qui pointent vers le même objet, ce qui reviendrait à dire que c'est bien pareil puisque s1 récupère la référence de instance (avec le return instance)

    Enfin la confusion vient aussi du fait que la variable de classe instance est du même type que la classe, ce qui m'embrouille à faire la distinction entre un objet Singleton (qui est une instance de la classe Singleton) et l'objet Singleton référencé par la variable private static instance. Je sais pas si je suis très clair

Discussions similaires

  1. Pattern singleton sur une JFrame
    Par Canartitude dans le forum Agents de placement/Fenêtres
    Réponses: 4
    Dernier message: 22/03/2014, 20h04
  2. Réponses: 2
    Dernier message: 26/12/2010, 22h08
  3. Problème sur une requête INSERT
    Par Marion dans le forum Langage SQL
    Réponses: 3
    Dernier message: 17/06/2003, 08h45
  4. problème sur une requête!!!!!
    Par Mcgrady_01 dans le forum Langage SQL
    Réponses: 2
    Dernier message: 13/06/2003, 01h17

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