[Padrão de design] Java multithreaded garantia 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.

Insira a descrição da imagem aqui
Insira a descrição da imagem aqui

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

    jjj
    Insira a descrição da imagem aqui

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.

Insira a descrição da imagem aqui

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

Insira a descrição da imagem aqui
Insira a descrição da imagem aqui
Insira a descrição da imagem aqui

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;
  }
} 

jjjjjjj

5. Use enumeração enum para obter singleton

Insira a descrição da imagem aqui

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

Insira a descrição da imagem aqui

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());
    }
  }
} 

Insira a descrição da imagem aqui

Acho que você gosta

Origin blog.csdn.net/weixin_40849588/article/details/114991697
Recomendado
Clasificación