[Servlet] Les singletons fonctionnent-ils avec la méthode init
5 réponses
Stéphane
Bonjour,
Je me tape la tête contre les murs car il y a quelque chose que je ne
comprends pas avec la méthode init des servlets. J'utilise Java 1.5 avec
un Tomcat 5.5.12.
Je voulais lancer un scheduler à partir de la méthode init de la
première servlet instanciée. Mais je me rends compte que le singleton
qui permet de créer l'instance du scheduler ne fonctionne pas comme je
le voudrais. Voici le code du singleton:
public class Singleton {
private static Object instance = null;
/**
* Singleton
*/
private Singleton() {}
public static synchronized Object newInstance() {
if (instance!=null) return(instance);
instance = new Object();
return(instance);
}
}
Et voici comment je l'appelle dans la méthode "init":
synchronized (System.out) {
System.out.println("@@@@ Thread n°"+Thread.currentThread().getId()+":
"+Singleton.newInstance());
}
Dans la méthode "init", j'obtiens ceci sur la console:
@@@@ Thread n°1: java.lang.Object@19113f8
@@@@ Thread n°1: java.lang.Object@17779e3
Deux instances de la servlet sont créées semble-t-il mais le singleton
retourne 2 instances différentes.
Si je fais la même chose dans la méthode "service" de la servlet et que
je l'appelle x fois, j'ai bien des lignes du genre:
@@@@ Thread n°32: java.lang.Object@425743
@@@@ Thread n°32: java.lang.Object@425743
@@@@ Thread n°31: java.lang.Object@425743
@@@@ Thread n°32: java.lang.Object@425743
@@@@ Thread n°31: java.lang.Object@425743
@@@@ Thread n°32: java.lang.Object@425743
Donc, d'ou vient le problème ?
Merci pour votre aide.
Stéphane
--
Plug'n dev
N'installez plus d'IDE pour développer en Java/J2EE/C/C++.
http://plugndev.toutprogrammer.com/
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
jeanlutrin
Salut,
Pour commencer, je me suis fait avoir par ta methode newInstance() qui ne cree pas une nouvelle instance : un nom tel getInstance() par exemple serait plus approprie ;)
Ensuite, ce n'est pas la bonne facon de creer un singleton. De nombreuses solutions plus complexes les unes que les autres ont ete proposees pour resoudre le probleme de la creation d'un singleton, y compris la solution tres creative (et tres boguee) nommee "double checked locking".
Ce probleme est tellement courant que des grands noms du monde Java ont publie un article a ce sujet, signe par de nombreuses authorites en la matiere (notamment Joshua Bloch et Doug Lea) :
Il existe pourtant quelques facons simples (et correctes) de creer un singleton. Par exemple :
public class Singleton { private static final Object INST = new Singleton();
private Singleton() {}
public static Object getInstance() { return INST; } }
Ca, ca t'assure que ta classe soit bien un singleton... Ton singleton sera instantie au chargement de la classe par le ClassLoader et ne sera pas collecte par le ramasse-miette tant que le ClassLoader existera. Il existe d'autres solutions si tu desires, par exemple, utiliser la "lazy initiation" pour ton singleton...
Si apres avoir change ton programme de test pour qu'il utilise un vrai singleton tu remarques toujours le meme probleme, c'est que plusieurs ClassLoader chargent ton singleton, par exemple parceque tu aurais deux Web apps differentes utilisant cette classe.
Si apres avoir modifie ton programme tu as toujours le probleme, il faut regarder du cote des ClassLoader. Le lien suivant pourra peut-etre t'aider :
Pour commencer, je me suis fait avoir par ta methode newInstance()
qui ne cree pas une nouvelle instance : un nom tel getInstance()
par exemple serait plus approprie ;)
Ensuite, ce n'est pas la bonne facon de creer un singleton. De
nombreuses solutions plus complexes les unes que les autres ont
ete proposees pour resoudre le probleme de la creation d'un
singleton, y compris la solution tres creative (et tres boguee)
nommee "double checked locking".
Ce probleme est tellement courant que des grands noms du monde
Java ont publie un article a ce sujet, signe par de nombreuses
authorites en la matiere (notamment Joshua Bloch et Doug Lea) :
Il existe pourtant quelques facons simples (et correctes) de creer un
singleton. Par exemple :
public class Singleton {
private static final Object INST = new Singleton();
private Singleton() {}
public static Object getInstance() {
return INST;
}
}
Ca, ca t'assure que ta classe soit bien un singleton... Ton singleton
sera instantie au chargement de la classe par le ClassLoader et ne
sera pas collecte par le ramasse-miette tant que le ClassLoader
existera. Il existe d'autres solutions si tu desires, par exemple,
utiliser la "lazy initiation" pour ton singleton...
Si apres avoir change ton programme de test pour qu'il utilise un
vrai singleton tu remarques toujours le meme probleme, c'est que
plusieurs ClassLoader chargent ton singleton, par exemple
parceque tu aurais deux Web apps differentes utilisant cette classe.
Si apres avoir modifie ton programme tu as toujours le probleme,
il faut regarder du cote des ClassLoader. Le lien suivant pourra
peut-etre t'aider :
Pour commencer, je me suis fait avoir par ta methode newInstance() qui ne cree pas une nouvelle instance : un nom tel getInstance() par exemple serait plus approprie ;)
Ensuite, ce n'est pas la bonne facon de creer un singleton. De nombreuses solutions plus complexes les unes que les autres ont ete proposees pour resoudre le probleme de la creation d'un singleton, y compris la solution tres creative (et tres boguee) nommee "double checked locking".
Ce probleme est tellement courant que des grands noms du monde Java ont publie un article a ce sujet, signe par de nombreuses authorites en la matiere (notamment Joshua Bloch et Doug Lea) :
Il existe pourtant quelques facons simples (et correctes) de creer un singleton. Par exemple :
public class Singleton { private static final Object INST = new Singleton();
private Singleton() {}
public static Object getInstance() { return INST; } }
Ca, ca t'assure que ta classe soit bien un singleton... Ton singleton sera instantie au chargement de la classe par le ClassLoader et ne sera pas collecte par le ramasse-miette tant que le ClassLoader existera. Il existe d'autres solutions si tu desires, par exemple, utiliser la "lazy initiation" pour ton singleton...
Si apres avoir change ton programme de test pour qu'il utilise un vrai singleton tu remarques toujours le meme probleme, c'est que plusieurs ClassLoader chargent ton singleton, par exemple parceque tu aurais deux Web apps differentes utilisant cette classe.
Si apres avoir modifie ton programme tu as toujours le probleme, il faut regarder du cote des ClassLoader. Le lien suivant pourra peut-etre t'aider :
[...] Si apres avoir change ton programme de test pour qu'il utilise un vrai singleton tu remarques toujours le meme probleme, c'est que plusieurs ClassLoader chargent ton singleton, par exemple parceque tu aurais deux Web apps differentes utilisant cette classe.
Je viens de faire le test avec le singleton que vous proposez mais le problème est le même.
Si apres avoir modifie ton programme tu as toujours le probleme, il faut regarder du cote des ClassLoader. Le lien suivant pourra peut-etre t'aider :
Je vais aller voir en espérant trouver la raison de cette bizarrerie.
Merci.
Stef
-- Plug'n dev N'installez plus d'IDE pour développer en Java/J2EE/C/C++. http://plugndev.toutprogrammer.com/
[...]
Si apres avoir change ton programme de test pour qu'il utilise un
vrai singleton tu remarques toujours le meme probleme, c'est que
plusieurs ClassLoader chargent ton singleton, par exemple
parceque tu aurais deux Web apps differentes utilisant cette classe.
Je viens de faire le test avec le singleton que vous proposez mais le
problème est le même.
Si apres avoir modifie ton programme tu as toujours le probleme,
il faut regarder du cote des ClassLoader. Le lien suivant pourra
peut-etre t'aider :
[...] Si apres avoir change ton programme de test pour qu'il utilise un vrai singleton tu remarques toujours le meme probleme, c'est que plusieurs ClassLoader chargent ton singleton, par exemple parceque tu aurais deux Web apps differentes utilisant cette classe.
Je viens de faire le test avec le singleton que vous proposez mais le problème est le même.
Si apres avoir modifie ton programme tu as toujours le probleme, il faut regarder du cote des ClassLoader. Le lien suivant pourra peut-etre t'aider :
Je vais aller voir en espérant trouver la raison de cette bizarrerie.
Merci.
Stef
-- Plug'n dev N'installez plus d'IDE pour développer en Java/J2EE/C/C++. http://plugndev.toutprogrammer.com/
obere
Les servlets ne sont instanciees qu'une seule fois: il n'y a pas une instance de servlet par requete, mais une seule instance de la servlet par laquelle passe toutes les requetes. Accessoirement cela veut dire que tu ne devrais pas avoir besopin d'un singleton pour ton object, si l'idee est de le partager entre les requetes sur tes servlets.
Pour en revenir a ton probleme, c'est assez etrange de voir deux logs sur le init de la servlet, puisque comme je l'ai dit la servlet ne devrait etre cree qu'une seule fois.
Est il possible qu'elle soit creee deux fois dans deux ClassLoader different (ce qui expliquerait aussi pourquoi ton singleton est cree deux fois) ?? Je ne connais pas assez Tomcat pour repondre, mais il pourrait etre utile de rajouter a ton log le class loader qui cree le singleton:
Les servlets ne sont instanciees qu'une seule fois: il n'y a pas une
instance de servlet par requete, mais une seule instance de la servlet
par laquelle passe toutes les requetes.
Accessoirement cela veut dire que tu ne devrais pas avoir besopin d'un
singleton pour ton object, si l'idee est de le partager entre les
requetes sur tes servlets.
Pour en revenir a ton probleme, c'est assez etrange de voir deux logs
sur le init de la servlet, puisque comme je l'ai dit la servlet ne
devrait etre cree qu'une seule fois.
Est il possible qu'elle soit creee deux fois dans deux ClassLoader
different (ce qui expliquerait aussi pourquoi ton singleton est cree
deux fois) ?? Je ne connais pas assez Tomcat pour repondre, mais il
pourrait etre utile de rajouter a ton log le class loader qui cree le
singleton:
Les servlets ne sont instanciees qu'une seule fois: il n'y a pas une instance de servlet par requete, mais une seule instance de la servlet par laquelle passe toutes les requetes. Accessoirement cela veut dire que tu ne devrais pas avoir besopin d'un singleton pour ton object, si l'idee est de le partager entre les requetes sur tes servlets.
Pour en revenir a ton probleme, c'est assez etrange de voir deux logs sur le init de la servlet, puisque comme je l'ai dit la servlet ne devrait etre cree qu'une seule fois.
Est il possible qu'elle soit creee deux fois dans deux ClassLoader different (ce qui expliquerait aussi pourquoi ton singleton est cree deux fois) ?? Je ne connais pas assez Tomcat pour repondre, mais il pourrait etre utile de rajouter a ton log le class loader qui cree le singleton:
On Tue, 21 Feb 2006 01:00:14 +0100, Stéphane wrote:
Bonjour,
Je me tape la tête contre les murs car il y a quelque chose que je ne comprends pas avec la méthode init des servlets. J'utilise Java 1.5 avec un Tomcat 5.5.12.
Je voulais lancer un scheduler à partir de la méthode init de la première servlet instanciée. Mais je me rends compte que le singleton
C'est pas directement la réponse, mais ça me semble plus simple : passe par un ServletContextListener.
On Tue, 21 Feb 2006 01:00:14 +0100, Stéphane
<spam_news@freelinuxdev.net> wrote:
Bonjour,
Je me tape la tête contre les murs car il y a quelque chose que je ne
comprends pas avec la méthode init des servlets. J'utilise Java 1.5 avec
un Tomcat 5.5.12.
Je voulais lancer un scheduler à partir de la méthode init de la
première servlet instanciée. Mais je me rends compte que le singleton
C'est pas directement la réponse, mais ça me semble plus simple :
passe par un ServletContextListener.
On Tue, 21 Feb 2006 01:00:14 +0100, Stéphane wrote:
Bonjour,
Je me tape la tête contre les murs car il y a quelque chose que je ne comprends pas avec la méthode init des servlets. J'utilise Java 1.5 avec un Tomcat 5.5.12.
Je voulais lancer un scheduler à partir de la méthode init de la première servlet instanciée. Mais je me rends compte que le singleton
C'est pas directement la réponse, mais ça me semble plus simple : passe par un ServletContextListener.