DEV Community

Tente isso 12-1: Semáforo controlado por computador

Exemplo prático:

Um programa de controle de semáforo.
Estados representados por uma enumeração: VERDE, AMARELO, VERMELHO.

1 Crie um arquivo chamado TrafficLightDemo.java

2 Comece definindo uma enumeração chamada TrafficLightColor que repre
sente os três estados do sinal, como mostrado aqui:
// Enumeração com as cores de um semáforo.
enum TrafficLightColor {
RED, GREEN, YELLOW
}

Sempre que a cor do sinal for necessária, seu valor na enumeração será usado

3 Em seguida, defina TrafficLightSimulator, como mostrado abaixo.
TrafficLightSimulator é a classe que encapsula a simulação do semáforo.

// Semáforo computadorizado.
class TrafficLightSimulator implements Runnable {
private Thread thrd; // contém a thread que executa a simulação
private TrafficLightColor tlc; // contém a cor do sinal
boolean stop = false; // configura com true para interromper a simulação
boolean changed = false; // true quando o sinal mudou
TrafficLightSimulator(TrafficLightColor init) {
tlc = init;
thrd = new Thread(this);
thrd.start();
}
TrafficLightSimulator() {
tlc = TrafficLightColor.RED;
thrd = new Thread(this);
thrd.start();
}

Observe que a classe TrafficLightSimulator implementa a interface Runnable para executar cada semáforo em uma thread separada, que percorre as cores. Possui dois construtores: um permite especificar a cor inicial e o outro define o vermelho como padrão, ambos iniciando uma nova thread.

As variáveis de instância incluem:
thrd: referência à thread do semáforo.
tlc: cor atual do semáforo.
stop: controla a interrupção da simulação (inicialmente false, permitindo o funcionamento contínuo).
changed: indica mudança de sinal (definida como true quando há alteração de cor).

4 Adicione o método run( ), mostrado a seguir, que começa a execução do semáforo.

// Inicia o semáforo.
public void run() {
while(!stop) {
try {
switch(tlc) {
case GREEN:
Thread.sleep(10000); // verde por 10 segundos
break;
case YELLOW:
Thread.sleep(2000); // amarelo por 2 segundos
break;
case RED:
Thread.sleep(12000); // vermelho por 12 segundos
break;
}
} catch(InterruptedException exc) {
System.out.println(exc);
}
changeColor();
}
}

O método percorre as cores do semáforo, colocando a execução em suspensão por um tempo adequado para a cor atual. Em seguida, chama o método changeColor() para alterar para a próxima cor na sequência.

5 Adicione o método changeColor( )
// Muda a cor.
synchronized void changeColor() {
switch(tlc) {
case RED:
tlc = TrafficLightColor.GREEN;
break;
case YELLOW:
tlc = TrafficLightColor.RED;
break;
case GREEN:
tlc = TrafficLightColor.YELLOW;
}
changed = true;
notify(); // sinaliza que a cor mudou
}

O método utiliza uma instrução switch para verificar a cor atual armazenada em tlc e atribuir a próxima cor da sequência. Ele é sincronizado para garantir que a chamada ao método notify() seja feita corretamente, sinalizando que ocorreu uma mudança de cor, já que notify() só pode ser chamado em um contexto sincronizado (apenas uma thread de cada vez possa executar).

6 O próximo método é waitForChange( ), que espera até a cor do sinal ser mudada.

// Espera até uma mudança de sinal ocorrer.
synchronized void waitForChange() {
try {
while(!changed)
wait(); // espera o sinal mudar
changed = false;
} catch(InterruptedException exc) {
System.out.println(exc);
}
}

O método waitForChange() chama wait(), o que faz com que a execução seja pausada até que o método changeColor() invoque notify(), sinalizando que a cor do semáforo foi alterada. Assim, waitForChange() só retornará após a mudança de cor.

7 Para concluir, adicione os métodos getColor( ), que retorna a cor atual do sinal, e cancel( ), que interrompe a thread do semáforo configurando stop com true.

// Retorna a cor atual.
synchronized TrafficLightColor getColor() {
return tlc;
}
// Interrompe o semáforo.
synchronized void cancel() {
stop = true;
}

Top comments (0)