J'utilise un bloc de code statique pour initialiser certains contrôleurs dans un registre que j'ai. Ma question est donc la suivante: puis-je garantir que ce bloc de code statique ne sera absolument appelé qu'une seule fois lors du premier chargement de la classe? Je comprends que je ne peux pas garantir quand ce bloc de code sera appelé, je suppose que c'est quand le Classloader le charge pour la première fois. Je me rends compte que je pourrais synchroniser sur la classe dans le bloc de code statique, mais je suppose que c'est en fait ce qui se passe de toute façon?
Un exemple de code simple serait;
class FooRegistry {
static {
//this code must only ever be called once
addController(new FooControllerImpl());
}
private static void addController(IFooController controller) {
// ...
}
}
ou devrais-je faire cela;
class FooRegistry {
static {
synchronized(FooRegistry.class) {
addController(new FooControllerImpl());
}
}
private static void addController(IFooController controller) {
// ...
}
}
Réponses:
Oui, les initialiseurs statiques Java sont thread-safe (utilisez votre première option).
Cependant, si vous voulez vous assurer que le code est exécuté exactement une fois, vous devez vous assurer que la classe n'est chargée que par un seul chargeur de classe. L'initialisation statique est effectuée une fois par chargeur de classe.
la source
Ceci est une astuce que vous pouvez utiliser pour une initialisation paresseuse
ou pour pré Java 5.0
Comme le bloc statique de SingletonHolder s'exécutera une fois de manière thread-safe, vous n'avez besoin d'aucun autre verrouillage. La classe SingletonHolder ne sera chargée que lorsque vous appelez instance ()
la source
Dans des circonstances habituelles, tout dans l'initialiseur statique se produit - avant tout ce qui utilise cette classe, donc la synchronisation n'est généralement pas nécessaire. Cependant, la classe est accessible à tout ce que l'intiailiser statique appelle (y compris en provoquant l'appel d'autres initialiseurs statiques).
Une classe peut être chargée par une classe chargée mais pas nécessairement initialisée immédiatement. Bien entendu, une classe peut être chargée par plusieurs instances de chargeurs de classe et ainsi devenir plusieurs classes avec le même nom.
la source
Oui, en quelque sorte
Un
static
initialiseur n'est appelé qu'une seule fois, donc selon cette définition, il est thread-safe - vous auriez besoin de deux ou plusieurs invocations de l'static
initialiseur pour même obtenir une contention de thread.Cela dit, les
static
initialiseurs sont déroutants à bien d'autres égards. Il n'y a vraiment aucun ordre spécifié dans lequel ils sont appelés. Cela devient vraiment déroutant si vous avez deux classes dont lesstatic
initialiseurs dépendent l'un de l'autre. Et si vous utilisez une classe mais n'utilisez pas ce que l'static
initialiseur configurera, vous n'êtes pas assuré que le chargeur de classe appellera l'initialiseur statique.Enfin, gardez à l'esprit les objets sur lesquels vous synchronisez. Je me rends compte que ce n'est pas vraiment ce que vous demandez, mais assurez-vous que votre question ne demande pas vraiment si vous devez rendre
addController()
thread-safe.la source
Oui, les initialiseurs statiques ne sont exécutés qu'une seule fois. Lisez ceci pour plus d'informations .
la source
Donc, fondamentalement, puisque vous voulez une instance singleton, vous devez le faire plus ou moins à l'ancienne et vous assurer que votre objet singleton est initialisé une et une seule fois.
la source