Padrão de design - padrão singleton (1)
1. Seis maneiras de escrever o modo singleton
(1) Modo homem faminto
public class Singleton {
private static Singleton singleton = new Singleton();
public Singleton() {
}
public static Singleton getInstance() {
return singleton;
}
}
1. Este método foi inicializado durante o processo de carregamento da classe, portanto a velocidade de carregamento é mais lenta, mas a velocidade de aquisição do objeto é rápida.
2. Com base no mecanismo de carregamento de classe, o problema de sincronização de multithreading é evitado. A instanciação é concluída quando a classe é carregada e o efeito de carregamento lento não é alcançado. fácil de desperdiçar memória
(2) Modo preguiçoso (thread inseguro)
public class Singleton {
private static Singleton singleton;
public Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
- 1. O modo lazy man declara um objeto estático, que é inicializado quando o usuário o chama pela primeira vez. Por um lado, economiza recursos, mas, por outro lado, precisa ser instanciado ao carregar pela primeira vez, a resposta é um pouco mais lenta e não pode funcionar normalmente quando multithreaded, e o thread não é seguro .
(3) Modo preguiçoso (segurança do fio)
public class Singleton {
private static Singleton singleton;
public Singleton() {
}
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
- 1. Essa maneira de escrever pode funcionar bem em multithreading, mas precisa ser sincronizada toda vez que o método getInstance é chamado. Isso causará sobrecarga de sincronização desnecessária e, na maioria das vezes, não precisamos de sincronização. Portanto, este modo não é recomendado.
(4) Modo de verificação dupla (DCL)
public class Singleton {
private volatile static Singleton singleton;
public Singleton() {
}
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
- 1. Essa maneira de escrever julga se está vazio duas vezes em getInstance. A primeira vez é para sincronização desnecessária e a segunda vez é para criar uma instância quando Singleton é igual a Null.
- 2. O uso de voláteis afetará mais ou menos o desempenho, mas considerando a correção, vale a pena sacrificar esse desempenho.
- 3. A vantagem do DCL é que a taxa de utilização de recursos é alta.O objeto singleton é instanciado quando getInstance é executado pela primeira vez e a eficiência é alta. A desvantagem é que a resposta é um pouco mais lenta ao carregar pela primeira vez e também apresenta alguns defeitos em um ambiente de alta simultaneidade. Embora o DCL resolva o consumo de recursos, a sincronização redundante, a segurança do encadeamento e outros problemas até certo ponto, ele falhará em alguns casos. É recomendável usar o modo singleton de classe interna estática em vez do DCL
(5) Modo singleton de classe interna estático
public class Singleton {
private Singleton() {
}
public static Singleton getInstance() {
return SingletonHolder.SINGLETON;
}
private static class SingletonHolder {
private static final Singleton SINGLETON = new Singleton();
}
}
- 1. Quando a classe Singleton for carregada pela primeira vez, getInstance não será inicializado, somente quando chamarmos o método getInstance, a máquina virtual carregará SingletonHolder e inicializará SINGLETON. Não apenas a segurança do encadeamento pode ser garantida, mas também a exclusividade da classe Singleton pode ser garantida.
(6) Enumerar singletons
public enum Singleton{
INSTANCE;
}
2. Cenários de uso do modo singleton
- Todo o projeto requer um ponto de acesso compartilhado ou dados compartilhados
- Criar um objeto que o ame requer muitos recursos, como acessar recursos como E/S ou bancos de dados.
- Objeto de ferramenta.