Simulação computacional: como funciona
Para compreender o funcionamento da simulação computacional, primeiramente vamos elencar alguns conceitos importantes:

Visão geral de um simulador

A figura abaixo ilustra um cenário que foi mapeado para um simulador computacional.

Os retângulos representam os blocos estáticos: um bloco de entrada, um bloco que é o balcão de atendimento e um bloco de saída. Um modelo de simulação tem dois blocos especiais que são os BlocoChegada (quando uma entidade chega no modelo) e o BlocoSaida (quando a entidade deixa o modelo).

No exemplo da figura, a pessoa que será atendida é uma entidade. Ela é criada no BlocoChegada em uma periodicidade que deve ser programada: as pessoas podem chegar, por exemplo, com um intervalo de tempo fixado, aleatório, conforme um distribuição normal ou qualquer outra forma que for adequada para simular o cenário.

Um simulador é uma aplicação single-thread. O algoritmo principal de um simulador consiste no seguinte pseudocódigo:

relogioSimulação = 0.0;
enquanto (listaEventosFuturos.tamanho() > 0) {
    evento = listaEventosFuturos.getProximo();
    relogioSimulação = evento.getHorario();
    evento.executar();
} // fim da simulação

Os blocos têm dois possíveis eventos associados: um de chegada (a entidade está chegando àquele bloco) ou de saída (a entidade está deixando o bloco). Sempre que um evento ocorre, outro evento deve ser criado e agendado para ser executado em alguma iteração futura do simulador.

Observe que a simulação só ocorre enquanto há eventos na lista de eventos futuros. Esta condição é imprescindível para que a simulação continue acontecendo.

Nota: você pode examinar o código-fonte no pacote atendimento para acompanhar as explicações que seguem.

Estudo de caso: o balcão de atendimento

O código-fonte está incluído com o simulador, que pode ser baixado aqui.

As linhas abaixo foram produzidas pela execução do exemplo do balcão de atendimento.

0.0: Pessoa(1) passou na porta e está indo para o balcão.
0.0: Pessoa(1) chegou direto ao balcão, sem fila.
11.0: Pessoa(2) passou na porta e está indo para o balcão.
11.0: Pessoa(2) foi colocada na fila de espera.
12.0: Pessoa(1) está deixando o balcão e indo para a saída.
12.0: Pessoa(2) está saindo da fila para ir ao balcão. Esperou 1.0 segundo(s).
12.0: Pessoa(1) chegou na porta de saída.
12.0: Pessoa(2) chegou direto ao balcão, sem fila.
18.0: Pessoa(3) passou na porta e está indo para o balcão.
18.0: Pessoa(3) foi colocada na fila de espera.
21.0: Pessoa(2) está deixando o balcão e indo para a saída.
21.0: Pessoa(3) está saindo da fila para ir ao balcão. Esperou 3.0 segundo(s).
21.0: Pessoa(2) chegou na porta de saída.
21.0: Pessoa(3) chegou direto ao balcão, sem fila.
25.0: Pessoa(4) passou na porta e está indo para o balcão.
25.0: Pessoa(4) foi colocada na fila de espera.
30.0: Pessoa(5) passou na porta e está indo para o balcão.
30.0: Pessoa(5) foi colocada na fila de espera.
43.0: Pessoa(3) está deixando o balcão e indo para a saída.
43.0: Pessoa(4) está saindo da fila para ir ao balcão. Esperou 18.0 segundo(s).
43.0: Pessoa(3) chegou na porta de saída.
43.0: Pessoa(4) chegou direto ao balcão, sem fila.
61.0: Pessoa(4) está deixando o balcão e indo para a saída.
61.0: Pessoa(5) está saindo da fila para ir ao balcão. Esperou 31.0 segundo(s).
61.0: Pessoa(4) chegou na porta de saída.
61.0: Pessoa(5) chegou direto ao balcão, sem fila.
70.0: Pessoa(5) está deixando o balcão e indo para a saída.
70.0: Pessoa(5) chegou na porta de saída.
As pessoas esperaram um total de 53 segundos.
O tempo médio de espera na fila foi de 13.25 segundos.

O número à esquerda é o relógio de simulação, em segundos. Ele mostra em que momento um certo evento ocorreu. Em seguida, o número da pessoa, para sabermos de quem se trata. E, por fim, a mensagem descrevendo o que ocorreu.

As duas últimas linhas mostram como se pode sumarizar informações estatísticas para serem analisadas após a simulação.

Agora vamos ao código-fonte.

// (1) instancia o simulador novo.
Simulador sim = new Simulador();

// (2) instancia o ponto de chegada das pessoas
PortaEntrada entrada = new PortaEntrada(sim);
BalcaoAtendimento balcao = new BalcaoAtendimento(sim);
PortaSaida saida = new PortaSaida(sim);

// (3) referências
entrada.setBalcaoAtendimento(balcao);
balcao.setPortaSaida(saida);

// (4) executa a simulação.
sim.executaSimulador();

Eis o que é feito: (1) instancia-se o simulador, vazio. Ele não tem nenhuma referência a nada. (2) Instancia-se os três blocos estáticos, PortaEntrada, BalcaoAtendimento e PortaSaida. (3) passamos a alguns blocos referências para os blocos seguintes, na seqüência em que se deslocam as entidades no modelo. (4) executa-se o simulador.

No momento em que PortaEntrada é instanciada, o construtor já cria o evento inicial de saída deste bloco. Confirme explicado, este evento é necessário para que a simulação seja iniciada.

--fim--

Conrado Vardanega - contato