* Le weblogue de SeB )
28 October 2013 • 9 Comments
Il Était Une Fois Le Singleton En Java
# Share $ Tweet % Pin & Mail ' SMS
Parmi tous les Design Patterns, le plus connu est)
*
sûrement le Singleton. Malheureusement, son
implémentation n’est pas aussi triviale qu’il n’y
parait en Java. Voici donc quelques exemples
d’implémentation…
Le weblogue de SeB
Parmi tous les , le plus connu est
sûrement le . Malheureusement, son
implémentation n’est pas aussi triviale qu’il n’y
parait en Java. Voici donc quelques exemples
d’implémentation…
Eager initialization
Si l’application a toujours besoin de cette instance
et que sa création ne mobilise pas trop de
ressource, il est acceptable de l’écrire ainsi :
public class EagerSingleton {
private static final EagerSingleton i
private EagerSingleton() {}
public static EagerSingleton getInsta
return instance;
}
}
Cependant, il est souvent nécessaire de retarder
le chargement de l’instance. De plus, lors de
l’implémentation d’un composant réutilisable, il
Si l’application a toujours besoin de cette instance
ne fautsa
pas imposernelemobilise
chargement de tous
et que création pas trop de les
singletons
ressource, àil l’application utilisatrice si ainsi
elle n’en a
est acceptable de l’écrire :
pas besoin !
Lazy initialization
Eager initialization
C’est pourquoi la première implémentation
réfléchie mais naïve qui vient à l’esprit est la
suivante :
1 public class LazyInitializationSing
Cependant,
2 il est souvent
private nécessaire
static de retarder
LazyInitialization
3
le chargement de l’instance. De plus, lors de
4 private LazyInitializationSinglet
l’implémentation
5 d’un composant réutilisable, il
6 paspublic static LazyInitializationS
ne faut imposer le chargement de
7 if (instance==null ) tous
{ les
singletons
8 à l’application
instance utilisatrice si elle n’en a
= new LazyInitializa
9 }
pas besoin !
10 return instance;
11 }
12 }
Elle semble juste. Cependant, elle n’est pas
C’est pourquoi la première implémentation
thread-safe. Dans un contexte multi-thread,
réfléchie mais naïve qui vient à l’esprit est la
plusieurs instances peuvent être créées.
suivante :
Double check thread-safe
Lazy initialization
Une fois que la problématique multi-thread est
prise en compte, le développeur est tenté de
l’implémenter de cette manière :
1 public class ThreadSafeSingleton {
2 private static ThreadSafeSingleto
3
4 private ThreadSafeSingleton() {}
5
Elle6semblepublic static ThreadSafeSingleton
juste. Cependant, elle n’est pas
7 if (instance==null) {
thread-safe.
8 Dans un contexte multi-thread,
synchronized (ThreadSafeSingl
9 if (instance==null) {
plusieurs instances peuvent être =
instance créées.
10 new ThreadSafe
11 }
12 }
13 }
14 return instance;
Une15 fois que
} la problématique multi-thread est
16 en }compte, le développeur est tenté de
prise
l’implémenter de cettedonne
Cette implémentation manière :
l’impression de
fonctionner. Or selon, le compilateur, la JVM ou
l’OS, le comportement peut différer. A tel point
Double
que check thread-safe
le “double check locking” est considéré
comme un antipattern. Java 5.0 étend la
sémantique du mot-clé volatile pour garantir le
“flush” des caches avant l’usage de la variable. En
utilisant cette solution, vous acceptez d’avoir un
code moins performant.
L’énumération
Dans la seconde édition d’Effective Java , Joshua
Cette implémentation
Bloch propose d’utiliser
donne
les enum
l’impression
pour de
implémenterOr
fonctionner. unselon,
singleton
le compilateur,
: la JVM ou
l’OS, . A tel point
1 public enum EnumSingleton {
que2 le “ INSTANCE; ” est considéré
3
comme un antipattern. Java 5.0 étend la
4 public static void doStuff() {
sémantique
5 du mot-clé
// do stuffvolatile pour garantir le
6
“flush” des} caches avant l’usage de la variable. En
7 }
utilisant cette solution, vous acceptez d’avoir un
Cette solution
code moins est terriblement simple mais
performant.
possède un inconvénient majeur : les
énumérations sont moins flexibles que les classes
(héritage, sérialisation, etc…).
Dans , Joshua
Bill Pugh
Bloch Singleton
propose d’utiliser les enum pour
implémenter un singleton :
Cette implémentation tente de réconcilier toutes
précédentes au moyen d’une classe imbriquée :
L’énumération
1
2
public class BillPughSingleton {
private BillPughSingleton() {}
3
4 static private class SingletonHel
5 private static final BillPughSi
6 solution
} est terriblement simple mais
Cette
7
possède
8 unpublic
inconvénient
staticmajeur : les
BillPughSingleton g
9 return [Link]
énumérations
10 } sont moins flexibles que les classes
(héritage,
11 } sérialisation, etc…).
Elle reprend le principe de la Eager initialization
sans avoir l’inconvénient identifié sur le lazy-
Cette implémentation
loading puisque la classe
tente
imbriquée
de réconcilier
n’est connue
toutes
précédentes
de [Link]
Enfin,
moyen
cette
d’une
implémentation
classe imbriquée
est :
thread-safe sans avoir à recourir à des mots-clés
du langage tels que synchronized, volatile ou enum.
Avant de terminer, sachez que si vous utilisez des
Bill Pugh Singleton
frameworks d’injection de dépendances tel que
Spring Framework, il est possible de le laisser
gérer vos classes comme des singletons.
Pourquoi vous avoir présenté toutes ces
implémentations ? Simplement
Elle reprend le principe pour
de la Eager montrer que
initialization
l’implémentation d’un Design
sans avoir l’inconvénient Pattern,
identifié aussi
sur le lazy-
simple
loading soit-il,
puisque n’est pas aussi
la classe triviale qu’il
imbriquée n’estn’y
connue
parait. Et la première
de personne. question
Enfin, cette à se poser est
implémentation est :
“Pourquoi
thread-safeutilise-t-on
sans avoirce modèle de
à recourir conception
à des mots-clés?”.
Il
duest également
langage recommandé
tels que de, bien
synchronized volatile ou enum.
documenter l’implémentation afin d’expliciter le
Avant de d’utilisation.
contexte terminer, sachez que si vous utilisez des
frameworks d’injection de dépendances tel que
Histoire à suivre… il est possible de le laisser
Spring Framework,
gérer vos classes comme des singletons.
Related Posts
Pourquoi vous avoir présenté toutes ces
implémentations ? Simplement pour montrer que
l’implémentation d’un Design Pattern, aussi
simple soit-il, n’est pas aussi triviale qu’il n’y
Modèle Et
parait. la première
d’anti- Java – questionJUnit
à se– poser
modèleest :
conception impossible
“Pourquoi utilise-t-on de d’anti-
ce modèle de conception ?”.
pour la gestion supprimer des conception
Il est également recommandé de bien
des exceptions éléments dans
documenter l’implémentation
une liste afin d’expliciter le
contexte d’utilisation.
Histoire à suivre…
Une JAXB – ignorer Eclipse JavaDoc
participation les espaces – génération
Related Posts
insignifiante inutiles dans automatique
parmi les les fichiers sur un Java
couches XML bean
applicatives
Previous Post Next Post
! Disqus - Un Service Nexus 5 - 8 Jours Plus
Social De Commentaires Tard "
Sur Votre Site
9 responses
Laurent Simon
31 October 2013
Désolé m’sieur, mais le “Double check test” n’a
JAMAIS été thread-safe, pas plus avec du JDK 1.4
qu’avec du 1.5. C’est simplement l’apparition des
Previousprocesseurs
Post Next
multi-coeurs qui ont permis Post
à pas
mal de développeurs de s’apercevoir qu’ils
faisaient une énorme connerie en pensant que
les transferts mémoire au niveau des caches
s’exécutaient nécessairement dans l’ordre ou il
étaient écrits dans le code source.
Autant que je me souvienne, même en JDK 1.2,
31 October 2013
on trouvait déjà des bugs issus de cette fausse
bonne idée. La propension à la manifestation du
phénomène
Laurent Simon dépend à la fois du hardware de
l’implémentation de la
Désolé m’sieur, mais leJVM utilisée.
“Double check test” n’a
JAMAIS été thread-safe, pas plus avec du JDK 1.4
9 responsesReply
qu’avec du 1.5. C’est simplement l’apparition des
processeurs multi-coeurs qui ont permis à pas
SeB
mal de développeurs de s’apercevoir qu’ils
faisaient
1 une
November énorme connerie en pensant que
2013
les transferts mémoire au niveau des caches
Effectivement, quand j’ai commencé cette note,
s’exécutaient nécessairement dans l’ordre ou il
pour moi le problème du “double check” venait
étaient écrits dans le code source.
du cache et avait été mis en exergue avec
l’apparition
Autant que jedes
meprocesseurs
souvienne, multi-coeurs.
même en JDKMais 1.2,
en me
on redocumentant
trouvait déjà des bugset ne trouvant
issus de cettepas les
fausse
articlesidée.
bonne que j’avais pu lire à l’origine,
La propension j’ai fait du
à la manifestation
quelques raccourcis
phénomène dépend maladroits
à la fois duet me suis de
hardware moi-
même embrouillé.de:-/laMerci
l’implémentation pour ta rectification !
JVM utilisée.
Que penses-tu si je remplace le paragraphe
erroné par celui-ci :
1 November 2013
“Cette implémentation donne l’impression de
fonctionner. Or selon, le compilateur, la JVM ou
l’OS,
SeB le comportement peut différer. A tel point
que le “double quand
Effectivement, check locking” est considéré
j’ai commencé cette note,
comme un antipattern. Java 5.0 introduit
pour moi le problème du “double check” venait le mot-
clé volatileetpour
du cache avaitrésoudre
été mis enceexergue
problème en
avec
acceptant
l’apparitiondedes
perdre en terme
processeurs de performance.”
multi-coeurs. Mais
en me redocumentant et ne trouvant pas les
Je peux garder cette référence
articles que j’avais pu lire à l’origine, j’ai fait
:[Link]
quelques raccourcis maladroits et me suis moi-
del/[Link] et peut-être
même embrouillé. :-/ Merci pour ta rectification !
ajouter celle-ci :
[Link]
Que penses-tu si je remplace le paragraphe
checked_locking
erroné par celui-ci :
“Cette implémentation donne l’impression de
Merci merci pour ta remarque pertinente !
fonctionner. Or selon, le compilateur, la JVM ou
l’OS,
Replyle comportement peut différer. A tel point
que le “double check locking” est considéré
comme un antipattern. Java 5.0 introduit le mot-
Laurent
clé volatileSimon
pour résoudre ce problème en
1 November 2013
acceptant de perdre en terme de performance.”
La correction que tu propose me paraît tout à
Je peux garder cette référence
fait appropriée.
:
J’enlèverais juste ce que tu dis suretl’introduction
peut-être
ajouter
du mot celle-ci : car il n’a pas été introduit par
clé volatile
java 5.0 mais a toujours existé (même en java
1.0).
Merci
Reply merci pour ta remarque pertinente !
Laurent
1 NovemberSimon
2013
1 November 2013
Pour l’utilisation
Laurent Simonde “volatile”, j’attirerais tout de
même l’attention sur le faît que ça ne fonctionne
La correction que tu propose me paraît tout à
qu’avec un JDK 5.0 ou plus car la sémantique du
fait appropriée.
mot clé a été étendue uniquement à partir de
cette version
J’enlèverais pour
juste cegarantir le “flush”
que tu dis des caches
sur l’introduction
(une
du motbarrière mémoire)
clé volatile car il avant
n’a pasusage de la
été introduit par
variable (lecture
java 5.0 mais ou écriture).
a toujours existé (même en java
1.0).
Reply
SeB
1 November 2013
1 November 2013
Laurent
Je viens deSimon
mettre à jour la note. Encore merci
pour l’utilisation
Pour tes remarques et suggestions
de “volatile”, de correction
j’attirerais tout de
!même l’attention sur le faît que ça ne fonctionne
qu’avec un JDK 5.0 ou plus car la sémantique du
Reply
mot clé a été étendue uniquement à partir de
cette version pour garantir le “flush” des caches
(une
SeB barrière mémoire) avant usage de la
variable (lecture
14 November 2013 ou écriture).
Après discussion, je vais enlever la remarque sur
le lazy-loading avec les enums. Il est respecté
1 November 2013
dans le cas général.
On
SeBpourrait juste reprocher qu’il n’est pas
maitrisé.
Je viens de mettre à jour la note. Encore merci
pour
Replytes remarques et suggestions de correction
!
Fatima Zahra MOUSSAID
29 November 2016
14 November 2013
comme l’implémentation Bill Pugh Singleton est
considérée
SeB la meilleure, peut-on l’utiliser tjrs, ou
y-a-il des limites ?
Après discussion, je vais enlever la remarque sur
le lazy-loading avec les enums. Il est respecté
Reply
dans le cas général.
On
SeBpourrait juste reprocher qu’il n’est pas
maitrisé.
1 December 2016
J’avoue être un peu rouillé sur l’implémentation
de singleton. N’ayant pas eu besoin de le faire
29 November 2016
depuis un long moment, je me demanderais
dans un premier temps s’il y a vraiment besoin
Fatima Zahra MOUSSAID
d’en implémenter un…
comme l’implémentation Bill Pugh Singleton est
Reply
considérée la meilleure, peut-on l’utiliser tjrs, ou
y-a-il des limites ?
fxrobin
17 December 2017
1 December 2016
Bonjour,
le
SeB classloader ne charge une classe qu’au
moment où elle commence à être utilisée par
J’avoue être un peu rouillé sur l’implémentation
une autre ByteCode.
de singleton. N’ayant pas eu besoin de le faire
Ainsi une classe ou instance n’est JAMAIS EAGER,
depuis un long moment, je me demanderais
sauf si on l’appelle explicitement, avec un
dans un premier temps s’il y a vraiment besoin
[Link](…) par exemple.
d’en implémenter un…
Faites, le test vous verrez qu’un Singleton ne se
charge pas tout seul …
Il faut une ligne de code qui l’appelle ou qui y
17 December 2017
fasse référence. Tant que ce n’est pas le cas, et
même si le programme tourne, le singleton n’est
pas en mémoire.
fxrobin
Bonjour,
Reply
le classloader ne charge une classe qu’au
moment où elle commence à être utilisée par
une autre ByteCode.
Ainsi une classe ou instance n’est JAMAIS EAGER,
sauf si on l’appelle explicitement, avec un
Leave a Reply
[Link](…) par exemple.
Faites, le test vous verrez qu’un Singleton ne se
charge
Your email pas toutwill
address seulnot
… be published.
Il faut une ligne de code qui l’appelle ou qui y
Comment
fasse référence. Tant que ce n’est pas le cas, et
même si le programme tourne, le singleton n’est
pas en mémoire.
Notify me of followup comments via e-mail
Comment
Your email address will not be published.
Name
Email
Leave a Reply
Website
Post me
Notify Comment
of followup comments via e-mail
Name
This site uses Akismet to reduce spam. Learn how
your comment data is processed.
Email
( Back to top
Website
Mobile Desktop
All content Copyright Le weblogue de SeB