the choco tankcriando instanciafilling the choco tankboiling the chocolatedraining the chocolateboiling the chocolatedraining the chocolateboiling the chocolatedraining the chocolateRepare na saida acima, como a frase "criando instancia" foi impressa 3 vezes. Logo, podemos concluir que foram criadas 3 instancias =/Alem disso, uma confusao geral aconteceu por ali. O tanque de chocolate foi preenchido mais de uma vez (derramando tudo pela sala...).A imagem abaixo mostra as threads que temos em execucao ao realizar um debug no eclipse.Agora imagine que cada thread seja trocada a tempo de cada uma alcancar a instrucao que cria a instancia de ChocolateBoiler como mostrado no screenshot do debug abaixo:O resultado e o que tivemos na saida mostrada como exemplo apos executar o codigo.Mas como corrigir isso?Uma das formas de corrigir este problema, e fazer com que o metodo estatico que retorna a instancia da classe, seja sincronizado. Desta forma, apenas uma thread por vez podera solicitar a criacao do objeto.Agora, temos o novo codigo da classe ChocolateBoiler sincronizando o metodo getInstance().package br.com.testes.patterns.singleton;public class ChocolateBoiler { private boolean empty; private boolean boiled; private static ChocolateBoiler instance; private ChocolateBoiler() { empty = true; boiled = false; System.out.println("criando instancia"); } public synchronized static ChocolateBoiler getInstance() { if (instance == null) { instance = new ChocolateBoiler(); } return instance; } public synchronized void fill() { if (isEmpty()) { System.out.println("filling the choco tank"); empty = false; boiled = false; } } public synchronized void drain() { if (!isEmpty() && isBoiled()) { System.out.println("draining the chocolate"); empty = true; } } public synchronized void boil() { if (!isEmpty() && !isBoiled()) { System.out.println("boiling the chocolate"); boiled = true; } } public boolean isEmpty() { return empty; } public boolean isBoiled() { return boiled; }}Executando o codigo novamente, tive a seguinte saida:criando instanciafilling the choco tankboiling the chocolatedraining the chocolateAgora veja como a execucao foi totalmente controlada. Nada de varias instancias, e nada de chocolate derramado...Existem outras formas de corrigir este problema sem sincronizar o metodo getInstance, uma vez que chamar metodos sincronizados tem um custo muito alto em uma aplicacao real.Uma alternativa citada pelo livro, e a de criar a instancia diretamente na declaracao do atributo da classe (not-lazily created instance).public class ChocolateBoiler { private boolean empty; private boolean boiled; private static ChocolateBoiler instance = new ChocolateBoiler(); private ChocolateBoiler() { empty = true; boiled = false; System.out.println("criando instancia"); } public static ChocolateBoiler getInstance() { return instance; } ... ...Outra alternativa que achei interessante foi a de so sincronizar a chamada quando a instancia ainda nao existir usando o conceito de double-checked locking.package br.com.testes.patterns.singleton;public class ChocolateBoiler { private boolean empty; private boolean boiled; private volatile static ChocolateBoiler instance; private ChocolateBoiler() { empty = true; boiled = false; System.out.println("criando instancia"); } public static ChocolateBoiler getInstance() { if (instance == null) { synchronized (ChocolateBoiler.class) { if (instance == null) { instance = new ChocolateBoiler(); } } } return instance; } ... ... // o resto do codigo continua igualBom... a ideia aqui foi alertar quanto a utilizacao do Singleton.Ate a proxima.