Artigo Diretório
-
- Análise de modo singleton
- O modo homem preguiçoso garante uma solução única
-
- 1. Implementação de palavra-chave sincronizada
- 2. Classes internas estáticas implementam o modo singleton
- 3. Serialização e desserialização para alcançar singleton
- 4. Use blocos de código estáticos para implementar singletons
- 5. Use enumeração enum para obter singleton
- 6. Melhorar o uso de enum para alcançar o modo singleton
Freqüentemente, usamos o modo singleton para resolver o problema de segurança de dados variáveis em cenários multithread ou simultâneos e evitar a geração de dados sujos.
Este artigo resume brevemente as várias implementações do padrão singleton em multithreading Java e compara as vantagens e desvantagens dessas implementações singleton.
O conteúdo do artigo foi extraído de: "Java Multithreaded Programming Core Technology" por Gao Hongyan
Análise de modo singleton
Carregue agora (modo homem com fome)
Carregar imediatamente : Quando precisarmos usar a classe, já criamos o objeto.
O modo homem faminto significa que a instância foi criada antes de chamar o método. O código de amostra é o seguinte:
package test;
public class MyObject{
private static MyObject myObject = new MyObject();
private MyObject(){
}
public static MyObject getInstance(){
return myObject;
}
}
Crie o código da classe de thread MyThread.java da seguinte maneira:
import test.MyObject;
public class MyThread extends Thread{
@Override
public void run(){
System.out.println(MyObject.getInstance().hashCode());
}
}
Crie uma classe principal de execução Run.java:
import extthread.MyThread;
public class Run{
public static void main(String[] args){
MyThread t1 = new MyThread();
MyThread t2 = new MyThread();
MyThread t3 = new MyThread();
t1.start();
t2.start();
t3.start();
}
}
Execute-o, podemos ver que o hashCode impresso (código hash, o identificador único da instância do objeto, semelhante ao número de identificação de cada um de nós) tem o mesmo valor. O cenário acima é o padrão de design singleton que carrega imediatamente.
Carregamento lento (modo homem preguiçoso)
Carregamento lento : refere-se à instância criada quando get () é chamado.
MyObject.java
package test;
public class MyObject{
private static MyObject myObject;
private MyObject(){
}
public static MyObject getInstance(){
//延迟加载
if(myObject == null){
myObject = new MyObject();
}
return myObject;
}
}
Embora o "carregamento lento" implemente o padrão de design singleton, em um ambiente multithread, o código de "carregamento lento" acima está completamente errado e não pode manter o estado do singleton.
O modo homem preguiçoso garante uma solução única
1. Implementação de palavra-chave sincronizada
-
Método de bloqueio getInstance (): baixa eficiência operacional
-
Classe de bloqueio (Object.class): baixa eficiência operacional
-
Sincronização de bloqueio separada para uma determinada parte do código importante: ainda há um certo risco de segurança multi-threaded
-
Use o mecanismo de bloqueio de dupla verificação DCL
2. Classes internas estáticas implementam o modo singleton
DCL pode resolver o problema de segurança de singleton multi-thread; outros métodos também podem obter o mesmo efeito.
3. Serialização e desserialização para alcançar singleton
Classes internas estáticas podem resolver problemas de segurança de thread. Mas se você usar o modo padrão para executar quando encontrar um objeto serializado, obterá muitos resultados.
Você pode usar o seguinte método readResolve () para resolver
4. Use blocos de código estáticos para implementar singletons
package test;
public class MyObject{
private static MyObject instance = null;
private MyObject(){
}
static{
instance = new MyObject();
}
public static MyObject getInstance(){
return instance;
}
}
5. Use enumeração enum para obter singleton
6. Melhorar o uso de enum para alcançar o modo singleton
O exemplo acima expõe a classe de enumeração, que viola o "princípio de responsabilidade única" e pode ser melhorada a seguir
O código MyThread.java é o seguinte
package extthread;
public class MyThread extends Thread{
@Override
public void run(){
for(int i=0; i< 5 ; i++){
System.out.println(MyObject.getConnection().hashCode());
}
}
}