Ao escrever o software, você geralmente precisa usar uma função de log de impressão, que pode ajudá -lo a depurar e posicionar o problema. Mas o método nativo de Java.out.println () raramente é usado no desenvolvimento real do projeto, e até ferramentas de verificação de código, como o FindBugs, pensarão que o uso do System.out.println () é um bug.
Por que o System.out.println (), que é um artefato iniciante em Java, será desprezado no desenvolvimento real do projeto? De fato, desde que você o analise com cuidado, você encontrará muitas desvantagens disso. Por exemplo, se não for controlado, todos os logs serão impressos como de costume após o lançamento do projeto, reduzindo assim a eficiência operacional; Você para distinguir em qual categoria este log está impresso.
Seu líder não é um tolo. No entanto, seu líder é muito bom e não permite que você obtenha uma ferramenta de log niubi com várias funções no início.
Essa demanda não é difícil para você.
Classe pública LOGUTIL {Public Final em Debug = 0; system.out.println (msg);}} public void info (string msg) {if (info> = nível) {system.out.println (msg);} public void ing msg) {if (erro> = nível) {System.out.println (msg);}}}
Imprima o log nessa classe e só precisa controlar o nível do nível para controlar livremente o conteúdo de impressão. Por exemplo, o projeto está agora em estágio de desenvolvimento e o nível está definido como depuração, para que todas as informações do log sejam impressas. Se o projeto estiver online, você poderá definir o nível para informações, para poder ver apenas o log e a impressão de log de nível acima. Se você deseja apenas ver o log errado, poderá definir o nível como erro. E se o projeto que você desenvolve for uma versão do cliente, você não deseja imprimir nenhum log, você pode definir o nível para nada. Você só precisa ligar para a impressão:
new Logutil ().
Você não pode esperar para apresentar esta ferramenta ao seu líder.
Mas não demorou muito para o seu líder encontrar você para dar feedback. Ele disse que, embora essa ferramenta seja fácil de usar, ela não distingue entre essas coisas. para usá -lo para usá -lo.
Você acha que seu líder é muito razoável e está tentando aproveitar essa oportunidade para praticar o modo de design, então você escreveu o seguinte código (PS: O código aqui é feito por mim e eu não prestei atenção a Eu não prestou atenção a ele.
Classe pública Logutil {private estático LogutilInInstance; GetInstance () {if (LogutilInstance == NULL) {LOGUTILINSTANCE = new LogUtil ();} retorna LogutilInstance;} public void debug (String g. {If (debug> = nível) {System.out.println (msg);} } Public void info (string msg) {if (info> = nível) {System.out.println (msg);} erro public void (string msg) {if (error> = nível) {System .out );}} Public static void main (string [] args) {Logutil.getInstance ().
Primeiro de tudo, o construtor do Logutil é privatizado, para que a nova palavra -chave não possa ser usada para criar uma instância de Logutil. Em seguida, use uma variável estática privada de slogutil para salvar a instância e forneça um método público GetInstance para obter uma instância de Logutil. Slogutil diretamente. Isso pode garantir que haverá apenas uma instância de Logutil na memória. Modo único está concluído! Neste momento, o código do log de impressão precisa ser alterado para a seguinte maneira:
Logutil.getInstance ().
Você mostra esta versão ao seu líder.
Você está cheio de suspeita, o modo de exemplo único não é realizado assim? O que pode ser bug?
Seu líder solicita que o uso de um modo de solteiros seja fazer com que essa classe tenha apenas uma instância na memória, mas você considera a situação de imprimir logs no multi -thread? Conforme mostrado no código a seguir:
Public static logutil getInstance () {if (logutilInstance == null) {LogutilInstance = new LogUtil ();} retornar LogutilInstance;}
Se houver dois threads, ao mesmo tempo, executando o método GetInstance ao mesmo tempo, o primeiro thread executa a segunda linha e ainda não executou a terceira linha. Dessa forma, seu modo de solteiros falha porque duas instâncias diferentes são criadas.
De repente, você percebe, mas seu pensamento é muito rápido e pensa imediatamente na solução.
Public sincronizado estático LOGUTIL GetInstance () {if (LogutilInstance == NULL) {LogUtilInstance = new Logutil ();} Retornar LogutilInstance;}
Dessa forma, apenas um thread pode executar o código no GetInstance ao mesmo tempo, que resolve efetivamente a situação em que as duas instâncias serão criadas acima.
Seu líder lê seu novo código e disse: "Bem, sim. Isso resolve a situação que pode criar duas instâncias, mas esse código ainda é um problema".
Você está nervoso, por que há algum problema?
Seu líder sorriu: "Não fique nervoso, desta vez não é um bug, mas pode ser otimizado em termos de desempenho. Veja, se você adicionar um método sincronizado ao método GetInstance, toda vez que eu for para o getInstace Método, serei sincronizado.
Primeiro remova a palavra -chave sincronizada da instrução Método e adicione -a ao corpo do método:
Public static Logutil getInstance () {if (LogUtilInstance == null) {Synchronized (Logutil.class) {if (LogutilInstance == null) {// pode ser necessário porque os dois processos podem ser anexados ao mesmo tempo no mesmo tempo ao mesmo tempo.
Depois que o código for alterado para isso, ele entrará na terceira linha quando o slogutil não for inicializado e adicionará o bloqueio síncrono. Assim que o slogutil for inicializado, ele não irá mais para a terceira linha, para que o método GetInstance não seja afetado por bloqueios de sincronização e a eficiência será melhorada até certo ponto.
Você não pode deixar de admirar.
Seu líder imediatamente se tornou humilde: "Esse método é chamado de bloqueio de check duas vezes, mas não penso nisso. Você pode verificar mais informações na Internet".
Na verdade, estou mais acostumado a usar o modo Man Hungry em Java
A característica do estilo preguiçoso é atrasada no carregamento.
A característica do estilo Han faminto é que ele é carregado no começo, para que você possa retornar diretamente quando o usar (eu recomendo mais isso, porque não há necessidade de considerar muitos problemas de segurança de threads. É claro que os bloqueios duplos mencionado para resolver o problema de sincronização)
O código de implementar registros de log com o estilo Han faminto é o seguinte:
Classe pública Logutil {private estático LogutilInstance = new Logutil (); () {} Public static logutil getInstance () {return logutilInstance;} public void debug (string msg) {if (debug> = nível) {system.out.print ln (msg);}} public void info (string msg) {if (info> = nível) {System.out.println (msg);}} public void Error (string msg) {if (error> = nível) {System.out.println (msg);} public atic void main main main main (String [] art) {Logutil.getInstance ().