Estou usando um bloco de código estático para inicializar alguns controladores em um registro que tenho. Minha pergunta é, portanto, posso garantir que esse bloco de código estático seja absolutamente chamado apenas uma vez quando a classe for carregada pela primeira vez? Entendo que não posso garantir quando esse bloco de código será chamado, acho que é quando o Classloader o carrega pela primeira vez. Sei que poderia sincronizar a classe no bloco de código estático, mas acho que isso é realmente o que acontece, afinal?
Um exemplo de código simples seria;
class FooRegistry {
static {
//this code must only ever be called once
addController(new FooControllerImpl());
}
private static void addController(IFooController controller) {
// ...
}
}
ou devo fazer isso;
class FooRegistry {
static {
synchronized(FooRegistry.class) {
addController(new FooControllerImpl());
}
}
private static void addController(IFooController controller) {
// ...
}
}
Respostas:
Sim, inicializadores estáticos Java são seguros para threads (use sua primeira opção).
No entanto, se você deseja garantir que o código seja executado exatamente uma vez, é necessário garantir que a classe seja carregada apenas por um único carregador de classes. A inicialização estática é executada uma vez por carregador de classes.
fonte
Este é um truque que você pode usar para inicialização lenta
ou para pré Java 5.0
Como o bloco estático no SingletonHolder será executado uma vez de maneira segura, você não precisará de nenhum outro bloqueio. A classe SingletonHolder só será carregada quando você chamar instance ()
fonte
Em circunstâncias normais, tudo no inicializador estático acontece - antes de tudo que usa essa classe, portanto, a sincronização geralmente não é necessária. No entanto, a classe é acessível a qualquer coisa que o intiailizador estático chame (inclusive fazendo com que outros inicializadores estáticos sejam invocados).
Uma classe pode ser carregada por uma classe carregada, mas não necessariamente inicializada imediatamente. Obviamente, uma classe pode ser carregada por várias instâncias de carregadores de classes e, assim, tornar-se várias classes com o mesmo nome.
fonte
Sim, mais ou menos
Um
static
inicializador é chamado apenas uma vez, portanto, por essa definição, ele é seguro para threads - você precisaria de duas ou mais invocações dostatic
inicializador para obter uma contenção de thread.Dito isto, os
static
inicializadores são confusos de muitas outras maneiras. Não há realmente nenhuma ordem especificada na qual eles são chamados. Isso fica realmente confuso se você tiver duas classes cujosstatic
inicializadores dependem um do outro. E se você usa uma classe, mas não usa o que ostatic
inicializador configurará, não há garantia de que o carregador de classes invocará o inicializador estático.Por fim, lembre-se dos objetos nos quais você está sincronizando. Sei que isso não é realmente o que você está perguntando, mas verifique se a sua pergunta não está realmente perguntando se você precisa tornar o
addController()
thread safe.fonte
Sim, inicializadores estáticos são executados apenas uma vez. Leia isto para mais informações .
fonte
Então, basicamente, como você deseja uma instância singleton, deve fazê-lo mais ou menos da maneira antiga e garantir que seu objeto singleton seja inicializado uma vez e apenas uma vez.
fonte