I wanted to implement a traffic signal (a single box). I saw there were many questions in SO, but I felt they were not complete code.
The below is the full source. I am using lock
and condition
for deciding which thread will actually run.
TrafficSignalSimulationUsingLock.java
package com.example.practice.third;
import java.util.concurrent.locks.Condition;
import com.example.practice.third.custom.lock.TrafficLock;
import com.example.practice.third.threads.GreenColorLightThread;
import com.example.practice.third.threads.RedColorLightThread;
import com.example.practice.third.threads.YellowColorLightThread;
public class TrafficSignalSimulationUsingLock {
public static void main(String[] args) throws InterruptedException {
TrafficLock lock = new TrafficLock();
Condition condition = lock.newCondition();
Thread redThread = new Thread(new RedColorLightThread(lock, condition));
Thread yellowThread = new Thread(new YellowColorLightThread(lock, condition));
Thread greenThread = new Thread(new GreenColorLightThread(lock, condition));
redThread.start();
Thread.sleep(300);
yellowThread.start();
greenThread.start();
redThread.join();
yellowThread.join();
greenThread.join();
}
}
RedColorLightThread.java
package com.example.practice.third.threads;
import java.util.concurrent.locks.Condition;
import com.example.practice.third.custom.lock.TrafficLock;
public class RedColorLightThread implements Runnable {
private TrafficLock trafficLock;
private Condition condition;
public RedColorLightThread(TrafficLock trafficLock, Condition condition) {
this.trafficLock = trafficLock;
this.condition = condition;
}
@Override
public void run() {
while (true) {
try {
trafficLock.lock();
while (trafficLock.isYellow() && trafficLock.isGreen()) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = 0; i < 5; i++) {
System.out.println("Red signal enabled");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
trafficLock.setYellow(true);
trafficLock.setGreen(false);
condition.signalAll();
} finally {
trafficLock.unlock();
}
}
}
}
YellowColorLightThread.java
package com.example.practice.third.threads;
import java.util.concurrent.locks.Condition;
import com.example.practice.third.custom.lock.TrafficLock;
public class YellowColorLightThread implements Runnable {
private TrafficLock trafficLock;
private Condition condition;
public YellowColorLightThread(TrafficLock trafficLock, Condition condition) {
this.trafficLock = trafficLock;
this.condition = condition;
}
@Override
public void run() {
while (true) {
try {
trafficLock.lock();
while (trafficLock.isRed() && trafficLock.isGreen()) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = 0; i < 3; i++) {
System.out.println("Yellow signal enabled");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
trafficLock.setRed(false);
trafficLock.setGreen(true);
condition.signalAll();
} finally {
trafficLock.unlock();
}
}
}
}
GreenColorLightThread.java
package com.example.practice.third.threads;
import java.util.concurrent.locks.Condition;
import com.example.practice.third.custom.lock.TrafficLock;
public class GreenColorLightThread implements Runnable {
private TrafficLock trafficLock;
private Condition condition;
public GreenColorLightThread(TrafficLock trafficLock, Condition condition) {
this.trafficLock = trafficLock;
this.condition = condition;
}
@Override
public void run() {
while (true) {
try {
trafficLock.lock();
while (trafficLock.isRed() && trafficLock.isYellow()) {
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = 0; i < 5; i++) {
System.out.println("Green signal enabled");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
trafficLock.setRed(true);
trafficLock.setYellow(false);
condition.signalAll();
} finally {
trafficLock.unlock();
}
}
}
}
TrafficLock.java
package com.example.practice.third.custom.lock;
import java.util.concurrent.locks.ReentrantLock;
public class TrafficLock extends ReentrantLock {
/**
*
*/
private static final long serialVersionUID = 7311233763066170670L;
private boolean red = true;
private boolean yellow = false;
private boolean green = false;
public TrafficLock() {
super(true);
}
public boolean isRed() {
return red;
}
public void setRed(boolean red) {
this.red = red;
}
public boolean isYellow() {
return yellow;
}
public void setYellow(boolean yellow) {
this.yellow = yellow;
}
public boolean isGreen() {
return green;
}
public void setGreen(boolean green) {
this.green = green;
}
}
The below is sample output:
Red signal enabled
Red signal enabled
Red signal enabled
Red signal enabled
Red signal enabled
Yellow signal enabled
Yellow signal enabled
Yellow signal enabled
Green signal enabled
Green signal enabled
Green signal enabled
Green signal enabled
Green signal enabled
Red signal enabled
Red signal enabled
Is this correct way of implementing (pls ignore space , time complexities).
Although this program gives result what I expect, I have a small doubt:
In each "color thread" (e.g. "RedColorLightThread"), the thread first sets the next desired state, followed by condition.signalAll()
and in finally block
releases the lock.
My doubt is, won't other threads get awake instantaneously when for example "red color thread" hasn't still released the lock?