I am trying to implement traffic signal using multithreading in Java. However, my code doesn't seem to work correctly. I intend to have each light run in a separate thread and want all three of them to synchronize among themselves to simulate traffic signal. Can you please suggest how to rectify this.
public class TrafficSignal implements Runnable {
public enum Color {RED, ORANGE, GREEN}
private Color color;
private static volatile Color previous = Color.ORANGE;
public TrafficSignal(Color color) {
this.color = color;
}
public synchronized void display() throws InterruptedException {
switch (color) {
case RED:
while (previous != Color.ORANGE) wait();
break;
case ORANGE:
while (previous != Color.GREEN) wait();
break;
case GREEN:
while (previous != Color.RED) wait();
break;
}
System.out.println(this.color);
Thread.sleep(1000);
previous = color;
notifyAll();
}
@Override
public void run() {
while (true) {
try {
display();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
new Thread(new TrafficSignal(TrafficSignal.Color.GREEN)).start();
new Thread(new TrafficSignal(TrafficSignal.Color.ORANGE)).start();
new Thread(new TrafficSignal(TrafficSignal.Color.RED)).start();
}
}
I think I'm able resolve it as below:
import java.util.Arrays;
import java.util.List;
public class TrafficSignal implements Runnable {
public enum Color {RED, ORANGE, GREEN}
private List<Color> light = Arrays.asList(Color.GREEN, Color.ORANGE, Color.RED);
private static volatile int counter = 0;
private int i;
private static final Object lock = new Object();
public TrafficSignal(Color color) {
this.i = light.indexOf(color);
}
@Override
public void run() {
try {
synchronized (lock) {
while (true) {
while (counter % light.size() != i) lock.wait();
System.out.println(Thread.currentThread().getName() + " :: " + light.get(counter % light.size()));
counter++;
Thread.sleep(1000);
lock.notifyAll();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new Thread(new TrafficSignal(TrafficSignal.Color.GREEN)).start();
new Thread(new TrafficSignal(TrafficSignal.Color.ORANGE)).start();
new Thread(new TrafficSignal(TrafficSignal.Color.RED)).start();
}
}