fix intersections starting independently with no coordination

This commit is contained in:
2025-11-18 14:29:11 +00:00
parent 72893f87ae
commit 06f079ce5b
3 changed files with 55 additions and 25 deletions

View File

@@ -171,6 +171,29 @@ public class IntersectionProcess {
System.out.println(" Routing configured.");
}
/**
* Requests permission for a traffic light to turn green.
* Blocks until permission is granted (no other light is green).
*
* @param direction The direction requesting green light
*/
public void requestGreenLight(String direction) {
trafficCoordinationLock.lock();
currentGreenDirection = direction;
}
/**
* Releases the green light permission, allowing another light to turn green.
*
* @param direction The direction releasing green light
*/
public void releaseGreenLight(String direction) {
if (direction.equals(currentGreenDirection)) {
currentGreenDirection = null;
trafficCoordinationLock.unlock();
}
}
/**
* Starts all traffic light threads.
*/

View File

@@ -29,7 +29,6 @@ public class TrafficLightThread implements Runnable {
@Override
public void run() {
// Capture the current thread reference
this.currentThread = Thread.currentThread();
this.running = true;
System.out.println("[" + light.getId() + "] Traffic light thread started.");
@@ -37,29 +36,37 @@ public class TrafficLightThread implements Runnable {
try {
while (running && !Thread.currentThread().isInterrupted()) {
// --- GREEN Phase ---
light.changeState(TrafficLightState.GREEN);
System.out.println("[" + light.getId() + "] State: GREEN");
// Request permission to turn green (blocks until granted)
process.requestGreenLight(light.getDirection());
processGreenLightQueue();
try {
// --- GREEN Phase ---
light.changeState(TrafficLightState.GREEN);
System.out.println("[" + light.getId() + "] State: GREEN");
if (!running || Thread.currentThread().isInterrupted()) break;
processGreenLightQueue();
// Wait for green duration
Thread.sleep((long) (light.getGreenTime() * 1000));
if (!running || Thread.currentThread().isInterrupted()) break;
if (!running || Thread.currentThread().isInterrupted()) break;
// Wait for green duration
Thread.sleep((long) (light.getGreenTime() * 1000));
// --- RED Phase ---
light.changeState(TrafficLightState.RED);
System.out.println("[" + light.getId() + "] State: RED");
if (!running || Thread.currentThread().isInterrupted()) break;
// --- RED Phase ---
light.changeState(TrafficLightState.RED);
System.out.println("[" + light.getId() + "] State: RED");
} finally {
// Always release the green light permission
process.releaseGreenLight(light.getDirection());
}
// Wait for red duration
Thread.sleep((long) (light.getRedTime() * 1000));
}
} catch (InterruptedException e) {
System.out.println("[" + light.getId() + "] Traffic light thread interrupted.");
// Restore interrupt status
Thread.currentThread().interrupt();
} finally {
this.running = false;

View File

@@ -1,18 +1,18 @@
package sd;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import sd.model.TrafficLight;
import sd.model.TrafficLightState;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.AfterEach;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import sd.model.TrafficLight;
import sd.model.TrafficLightState;
/**
* Test class to verify traffic light coordination within an intersection.
@@ -108,7 +108,7 @@ public class TrafficLightCoordinationTest {
assertTrue(maxGreenSimultaneously.get() <= 1,
"At most ONE light should be GREEN at any time. Found: " + maxGreenSimultaneously.get());
System.out.println("\nTraffic light coordination working correctly!");
System.out.println("\nTraffic light coordination working correctly!");
}
/**