mirror of
https://github.com/davidalves04/Trabalho-Pratico-SD.git
synced 2025-12-08 20:43:32 +00:00
Compare commits
7 Commits
13-create-
...
16-integra
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a31ac61a9a | ||
| 5dc1b40c88 | |||
| 3117bdf332 | |||
| 1140c3ca48 | |||
|
|
484cba1eee | ||
|
|
0e5526c3f6 | ||
|
|
4710c96450 |
@@ -12,10 +12,10 @@ import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import sd.config.SimulationConfig;
|
||||
import sd.engine.TrafficLightThread;
|
||||
import sd.model.Intersection;
|
||||
import sd.model.MessageType;
|
||||
import sd.model.TrafficLight;
|
||||
import sd.model.TrafficLightState;
|
||||
import sd.model.Vehicle;
|
||||
import sd.protocol.MessageProtocol;
|
||||
import sd.protocol.SocketConnection;
|
||||
@@ -176,134 +176,25 @@ public class IntersectionProcess {
|
||||
System.out.println("\n[" + intersectionId + "] Starting traffic light threads...");
|
||||
|
||||
for (TrafficLight light : intersection.getTrafficLights()) {
|
||||
trafficLightPool.submit(() -> runTrafficLightCycle(light));
|
||||
|
||||
TrafficLightThread lightTask = new TrafficLightThread(light, this, config);
|
||||
|
||||
|
||||
trafficLightPool.submit(lightTask);
|
||||
|
||||
System.out.println(" Started thread for: " + light.getDirection());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The main loop for a traffic light thread.
|
||||
* Continuously cycles between green and red states.
|
||||
*
|
||||
* only one traffic light can be green at any given time in this intersection.
|
||||
*
|
||||
* @param light The traffic light to control.
|
||||
*/
|
||||
private void runTrafficLightCycle(TrafficLight light) {
|
||||
System.out.println("[" + light.getId() + "] Traffic light thread started.");
|
||||
|
||||
while (running) {
|
||||
try {
|
||||
// Acquire coordination lock to become green
|
||||
trafficCoordinationLock.lock();
|
||||
try {
|
||||
// Wait until no other direction is green
|
||||
while (currentGreenDirection != null && running) {
|
||||
trafficCoordinationLock.unlock();
|
||||
Thread.sleep(100); // Brief wait before retrying
|
||||
trafficCoordinationLock.lock();
|
||||
}
|
||||
|
||||
if (!running) {
|
||||
break; // Exit if shutting down
|
||||
}
|
||||
|
||||
// Mark this direction as the current green light
|
||||
currentGreenDirection = light.getDirection();
|
||||
light.changeState(TrafficLightState.GREEN);
|
||||
System.out.println("[" + light.getId() + "] State: GREEN");
|
||||
|
||||
} finally {
|
||||
trafficCoordinationLock.unlock();
|
||||
}
|
||||
|
||||
// Process vehicles while green
|
||||
processGreenLight(light);
|
||||
|
||||
// Wait for green duration
|
||||
Thread.sleep((long) (light.getGreenTime() * 1000));
|
||||
|
||||
// Release coordination lock (turn red)
|
||||
trafficCoordinationLock.lock();
|
||||
try {
|
||||
light.changeState(TrafficLightState.RED);
|
||||
currentGreenDirection = null; // Release exclusive access
|
||||
System.out.println("[" + light.getId() + "] State: RED (RELEASED ACCESS)");
|
||||
} finally {
|
||||
trafficCoordinationLock.unlock();
|
||||
}
|
||||
|
||||
// Wait for red duration
|
||||
Thread.sleep((long) (light.getRedTime() * 1000));
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println("[" + light.getId() + "] Traffic light thread interrupted.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("[" + light.getId() + "] Traffic light thread stopped.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes vehicles when a traffic light is GREEN.
|
||||
* Dequeues vehicles and sends them to their next destination.
|
||||
*
|
||||
* @param light The traffic light that is currently green.
|
||||
*/
|
||||
private void processGreenLight(TrafficLight light) {
|
||||
while (light.getState() == TrafficLightState.GREEN && light.getQueueSize() > 0) {
|
||||
Vehicle vehicle = light.removeVehicle();
|
||||
|
||||
if (vehicle != null) {
|
||||
// Get crossing time based on vehicle type
|
||||
double crossingTime = getCrossingTimeForVehicle(vehicle);
|
||||
|
||||
// Simulate crossing time
|
||||
try {
|
||||
Thread.sleep((long) (crossingTime * 1000));
|
||||
} catch (InterruptedException e) {
|
||||
Thread.currentThread().interrupt();
|
||||
break;
|
||||
}
|
||||
|
||||
// Update vehicle statistics
|
||||
vehicle.addCrossingTime(crossingTime);
|
||||
|
||||
// Update intersection statistics
|
||||
intersection.incrementVehiclesSent();
|
||||
|
||||
// Send vehicle to next destination
|
||||
sendVehicleToNextDestination(vehicle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the crossing time for a vehicle based on its type.
|
||||
*
|
||||
* @param vehicle The vehicle.
|
||||
* @return The crossing time in seconds.
|
||||
*/
|
||||
private double getCrossingTimeForVehicle(Vehicle vehicle) {
|
||||
switch (vehicle.getType()) {
|
||||
case BIKE:
|
||||
return config.getBikeVehicleCrossingTime();
|
||||
case LIGHT:
|
||||
return config.getLightVehicleCrossingTime();
|
||||
case HEAVY:
|
||||
return config.getHeavyVehicleCrossingTime();
|
||||
default:
|
||||
return config.getLightVehicleCrossingTime();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a vehicle to its next destination via socket connection.
|
||||
*
|
||||
* @param vehicle The vehicle that has crossed this intersection.
|
||||
*/
|
||||
private void sendVehicleToNextDestination(Vehicle vehicle) {
|
||||
public void sendVehicleToNextDestination(Vehicle vehicle) {
|
||||
String nextDestination = vehicle.getCurrentDestination();
|
||||
|
||||
try {
|
||||
|
||||
158
main/src/main/java/sd/engine/TrafficLightThread.java
Normal file
158
main/src/main/java/sd/engine/TrafficLightThread.java
Normal file
@@ -0,0 +1,158 @@
|
||||
package sd.engine;
|
||||
|
||||
import sd.IntersectionProcess;
|
||||
import sd.config.SimulationConfig;
|
||||
import sd.model.TrafficLight;
|
||||
import sd.model.TrafficLightState;
|
||||
import sd.model.Vehicle;
|
||||
|
||||
/**
|
||||
* Implements the control logic for a single TrafficLight
|
||||
* as a Runnable task that runs in its own Thread.
|
||||
*
|
||||
*/
|
||||
public class TrafficLightThread implements Runnable {
|
||||
|
||||
/**
|
||||
* The TrafficLight object (the *model*) that this thread controls.
|
||||
* Contains the queue and the state.
|
||||
*/
|
||||
private final TrafficLight light;
|
||||
|
||||
/**
|
||||
* The IntersectionProcess (the Process) that "owns" this thread.
|
||||
* Used to call methods on the process, such as sendVehicleToNextDestination().
|
||||
*/
|
||||
private final IntersectionProcess process;
|
||||
|
||||
/**
|
||||
* The simulation configuration, used to get timings (e.g., crossing time).
|
||||
*/
|
||||
private final SimulationConfig config;
|
||||
|
||||
/**
|
||||
* Volatile flag to control the graceful shutdown mechanism.
|
||||
* When set to 'false', the 'run()' loop terminates.
|
||||
*/
|
||||
private volatile boolean running;
|
||||
|
||||
/**
|
||||
* Constructor for the Traffic Light Thread.
|
||||
*
|
||||
* @param light The TrafficLight object (model) to be controlled.
|
||||
* @param process The parent IntersectionProcess (for callbacks).
|
||||
* @param config The simulation configuration (to get timings).
|
||||
*/
|
||||
public TrafficLightThread(TrafficLight light, IntersectionProcess process, SimulationConfig config) {
|
||||
this.light = light;
|
||||
this.process = process;
|
||||
this.config = config;
|
||||
this.running = false; // Starts as 'stopped'
|
||||
}
|
||||
|
||||
/**
|
||||
* The main entry point for the thread.
|
||||
* Implements the GREEN/RED cycle logic extracted from IntersectionProcess.
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
this.running = true;
|
||||
System.out.println("[" + light.getId() + "] Traffic light thread started.");
|
||||
|
||||
try {
|
||||
// Main thread loop, continues while 'running' is true
|
||||
// This 'running' flag is controlled by the parent IntersectionProcess
|
||||
while (running) {
|
||||
|
||||
// --- GREEN Phase ---
|
||||
light.changeState(TrafficLightState.GREEN); //
|
||||
System.out.println("[" + light.getId() + "] State: GREEN");
|
||||
|
||||
// Process vehicles in the queue
|
||||
processGreenLightQueue();
|
||||
|
||||
// Wait for green duration
|
||||
Thread.sleep((long) (light.getGreenTime() * 1000)); //
|
||||
|
||||
if (!running) break; // Check flag after sleep
|
||||
|
||||
// --- RED Phase ---
|
||||
light.changeState(TrafficLightState.RED); //
|
||||
System.out.println("[" + light.getId() + "] State: RED");
|
||||
|
||||
// Wait for red duration
|
||||
Thread.sleep((long) (light.getRedTime() * 1000)); //
|
||||
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
// Apanha a InterruptedException (outra forma de parar a thread)
|
||||
System.out.println("[" + light.getId() + "] Traffic light thread interrupted.");
|
||||
this.running = false; // Garante que o loop termina
|
||||
}
|
||||
|
||||
System.out.println("[" + light.getId() + "] Traffic light thread stopped.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes vehicles in the queue while the traffic light is GREEN.
|
||||
* Logic extracted from IntersectionProcess.processGreenLight()
|
||||
*
|
||||
*/
|
||||
private void processGreenLightQueue() throws InterruptedException {
|
||||
//
|
||||
while (running && light.getState() == TrafficLightState.GREEN && light.getQueueSize() > 0) {
|
||||
|
||||
Vehicle vehicle = light.removeVehicle(); //
|
||||
|
||||
if (vehicle != null) {
|
||||
// 1. Get the crossing time (t_sem)
|
||||
double crossingTime = getCrossingTimeForVehicle(vehicle); //
|
||||
|
||||
// 2. Simulate the time the vehicle takes to cross
|
||||
Thread.sleep((long) (crossingTime * 1000)); //
|
||||
|
||||
// 3. Update vehicle statistics
|
||||
vehicle.addCrossingTime(crossingTime); //
|
||||
|
||||
// 4. Update intersection statistics
|
||||
|
||||
process.getIntersection().incrementVehiclesSent(); //
|
||||
|
||||
// 5. Call the parent Process to send the vehicle
|
||||
|
||||
process.sendVehicleToNextDestination(vehicle); //
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the crossing time for a vehicle based on its type.
|
||||
* Logic extracted from IntersectionProcess.getCrossingTimeForVehicle()
|
||||
*
|
||||
*
|
||||
* @param vehicle The vehicle.
|
||||
* @return The crossing time in seconds.
|
||||
*/
|
||||
private double getCrossingTimeForVehicle(Vehicle vehicle) {
|
||||
switch (vehicle.getType()) { //
|
||||
case BIKE:
|
||||
return config.getBikeVehicleCrossingTime(); //
|
||||
case LIGHT:
|
||||
return config.getLightVehicleCrossingTime(); //
|
||||
case HEAVY:
|
||||
return config.getHeavyVehicleCrossingTime(); //
|
||||
default:
|
||||
return config.getLightVehicleCrossingTime(); //
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the thread to stop gracefully (graceful shutdown).
|
||||
* Sets the 'running' flag to false. The thread will finish
|
||||
* its current sleep cycle and exit the 'run()' loop.
|
||||
*/
|
||||
public void shutdown() {
|
||||
this.running = false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user