This commit is contained in:
violette 2024-03-24 23:36:50 -04:00
parent 3b99a35740
commit 16fe398f5f
4 changed files with 135 additions and 79 deletions

View file

@ -13,22 +13,24 @@ public class App {
static private int numStopPerBus = 8; static private int numStopPerBus = 8;
static private int numStops = numBusses * numStopPerBus; static private int numStops = numBusses * numStopPerBus;
static private int numPassengersPerBus = 10; static private int numPassengersPerBus = 10;
static private int numPassengersPerStop = 3; static private int numPassengersPerStop = 3;
static private int numPassengers = numPassengersPerStop * numStops; static private int numPassengers = numPassengersPerStop * numStops;
static private int numThreadsBus = 5; static private int numThreadsBus = 5;
static private int numThreadsStop = 2; static private int numThreadsStop = 2;
static private int timeBetweenStops = 5; static private int timeBetweenStops = 5;
static private int timeEmbark = 2; static private int timeEmbark = 2;
public static void main(String[] args) { public static void main(String[] args) {
ExecutorService threadsBus = Executors.newFixedThreadPool(numThreadsBus); ExecutorService threadsBus = Executors.newFixedThreadPool(numThreadsBus);
ExecutorService threadsStop = Executors.newFixedThreadPool(numThreadsStop); ExecutorService threadsStop = Executors.newFixedThreadPool(numThreadsStop);
ArrayList<Stop> stops = new ArrayList<Stop>(); ExecutorService threadsPassenger = Executors.newFixedThreadPool(1); // doesnt need more! future balance
ArrayList<Bus> busses = new ArrayList<Bus>(); // themselfes out.
ArrayList<Passenger> passengers = new ArrayList<Passenger>(); ArrayList<Stop> stops = new ArrayList<Stop>();
BlockingQueue<BusInformationMessage> blockingQueue = new LinkedBlockingQueue<BusInformationMessage>(); ArrayList<Bus> busses = new ArrayList<Bus>();
ArrayList<Passenger> passengers = new ArrayList<Passenger>();
BlockingQueue<BusInformationMessage> blockingQueue = new LinkedBlockingQueue<BusInformationMessage>();
// make stops // make stop" + name + " reached stop " + nextStop.getStopName() + "!"s
for (int k = 0; k < numStops; k++) { for (int k = 0; k < numStops; k++) {
Stop s = new Stop(k, numPassengersPerStop); Stop s = new Stop(k, numPassengersPerStop);
s.setBlockingQueue(blockingQueue); s.setBlockingQueue(blockingQueue);
@ -36,14 +38,14 @@ public class App {
stops.add(s); stops.add(s);
s.setThreadPool(threadsStop); s.setThreadPool(threadsStop);
threadsStop.submit(s); threadsStop.submit(s);
//s.run();
} }
// make busses // make busses
for (int k = 0; k < numBusses; k++) { for (int k = 0; k < numBusses; k++) {
if (numStopPerBus > numStops) if (numStopPerBus > numStops) {
{System.out.println("More stops per bus than stops."); return;} System.out.println("More stops per bus than stops.");
return;
}
ArrayList<Stop> s_list = new ArrayList<Stop>(); ArrayList<Stop> s_list = new ArrayList<Stop>();
Stop s; Stop s;
@ -67,7 +69,7 @@ public class App {
for (Stop start : b.getStops()) { for (Stop start : b.getStops()) {
// make sure passenger can leave. // make sure passenger can leave.
if (start == b.getTerminus()) if (start == b.getTerminus())
continue; continue;
int idx = b.getStops().indexOf(start); int idx = b.getStops().indexOf(start);
@ -80,9 +82,12 @@ public class App {
dest = b.getStops().get(idx + 1 + (int) Math.round(Math.random() * (numStopPerBus - 2 - idx))); dest = b.getStops().get(idx + 1 + (int) Math.round(Math.random() * (numStopPerBus - 2 - idx)));
Passenger p = new Passenger(idPassenger, start, dest); Passenger p = new Passenger(idPassenger, start, dest);
p.setThreadPool(threadsPassenger);
passengers.add(p); passengers.add(p);
start.addPassenger(p); start.addPassenger(p);
idPassenger++; idPassenger++;
threadsPassenger.submit(p);
} }
} }
} }
@ -106,11 +111,15 @@ public class App {
threadsBus.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); threadsBus.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
} catch (InterruptedException e) {} } catch (InterruptedException e) {}
// block stop pool once bus have finished // block stop and passenger pool once bus have finished
threadsStop.shutdown(); threadsStop.shutdown();
threadsPassenger.shutdown();
try { try {
threadsStop.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); threadsStop.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
} catch (InterruptedException e) {} } catch (InterruptedException e) {}
try {
threadsPassenger.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
} catch (InterruptedException e) {}
} }
} }

View file

@ -2,19 +2,20 @@ package usherbrooke.ift630;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutionException;
public class Bus extends Thread { public class Bus extends Thread {
private ArrayList<Passenger> passengers; private ArrayList<Passenger> passengers;
private ArrayList<Stop> stops; private ArrayList<Stop> stops;
private String name; private String name;
private int id; private int id;
private int maxCapacity; private int maxCapacity;
private int currentCapacity; private int currentCapacity;
private int timeBetweenStops; private int timeBetweenStops;
private int timeToNextStop; private int timeToNextStop;
private int timeEmbark; private int timeEmbark;
private Stop nextStop; private Stop nextStop;
private BlockingQueue<BusInformationMessage> blockingQueue; private BlockingQueue<BusInformationMessage> blockingQueue;
// returns time for a single passenger to embark. // returns time for a single passenger to embark.
private int timeEmbark() { private int timeEmbark() {
@ -23,14 +24,14 @@ public class Bus extends Thread {
// set time between stop. // set time between stop.
private int calculateTimeBetweenStops() { private int calculateTimeBetweenStops() {
timeToNextStop = (int) ((timeBetweenStops / 3) + (Math.random() * 2 * timeBetweenStops / 3)); timeToNextStop = (int) ((timeBetweenStops / 3) + (Math.random() * 2 * timeBetweenStops / 3));
return timeToNextStop; return timeToNextStop;
} }
// check if a passenger must leave at next stop. // check if a passenger must leave at next stop.
private boolean stopAsked() { private boolean stopAsked() {
boolean res = false; boolean res = false;
for (Passenger p : passengers){ for (Passenger p : passengers) {
if (p.getDest() == nextStop) { if (p.getDest() == nextStop) {
res = true; res = true;
Logger.getInstance().print(id, "[BUS] " + name + " stop asked!"); Logger.getInstance().print(id, "[BUS] " + name + " stop asked!");
@ -65,9 +66,9 @@ public class Bus extends Thread {
} }
// send Bus info msg to next stop // send Bus info msg to next stop
private void sendNextStopInfo() throws InterruptedException{ private void sendNextStopInfo() throws InterruptedException {
BusInformationMessage info = new BusInformationMessage(this, nextStop, timeToNextStop); BusInformationMessage info = new BusInformationMessage(this, nextStop, timeToNextStop);
synchronized(blockingQueue) { synchronized (blockingQueue) {
blockingQueue.put(info); blockingQueue.put(info);
} }
} }
@ -120,22 +121,22 @@ public class Bus extends Thread {
nextStop = null; nextStop = null;
} }
} }
} catch (InterruptedException e) { } catch (Exception e) {
Logger.getInstance().print(id, "[BUS] exception: " + e.toString()); Logger.getInstance().print(id, "[BUS] exception: " + e.toString());
} }
Logger.getInstance().print(id, "[BUS] " + name + " exiting!"); Logger.getInstance().print(id, "[BUS] " + name + " exiting!");
} }
Bus(ArrayList<Stop> s, int id, int timeStop, int timeEmbark, int maxCapacity) { Bus(ArrayList<Stop> s, int id, int timeStop, int timeEmbark, int maxCapacity) {
this.timeBetweenStops = timeStop * 1000 + 1; this.timeBetweenStops = timeStop * 1000 + 1;
this.timeEmbark = timeEmbark * 1000 + 1; this.timeEmbark = timeEmbark * 1000 + 1;
this.name = "Bus n°" + id; this.name = "Bus n°" + id;
this.id = id; this.id = id;
this.passengers = new ArrayList<Passenger>(); this.passengers = new ArrayList<Passenger>();
this.stops = s; this.stops = s;
this.nextStop = stops.get(0); this.nextStop = stops.get(0);
this.currentCapacity = 0; this.currentCapacity = 0;
this.maxCapacity = maxCapacity; this.maxCapacity = maxCapacity;
} }
// disembark passenger at a stop. Synchronizes, locks on that stop, and waits. // disembark passenger at a stop. Synchronizes, locks on that stop, and waits.
@ -145,11 +146,11 @@ public class Bus extends Thread {
for (Passenger p : passengers) { for (Passenger p : passengers) {
waitEmbark(); waitEmbark();
Logger.getInstance().print(id,
"\t[DISEMBARK] " + p.getName() + " at " + nextStop.getStopName());
if (p.getDest() == nextStop) { if (p.getDest() == nextStop) {
p.disembark(); synchronized (p) {
p.notify();
}
// already synced on this, func is synced
currentCapacity--; currentCapacity--;
} }
} }
@ -163,15 +164,15 @@ public class Bus extends Thread {
try { try {
ArrayList<Passenger> list = nextStop.getPassengerByDest(stops); ArrayList<Passenger> list = nextStop.getPassengerByDest(stops);
for (Passenger p : list) { for (Passenger p : list) {
synchronized (p) {
p.notify();
}
waitEmbark(); waitEmbark();
if (currentCapacity >= maxCapacity) if (currentCapacity >= maxCapacity)
continue; continue;
passengers.add(p); passengers.add(p);
nextStop.removePassenger(p); nextStop.removePassenger(p);
currentCapacity++; currentCapacity++;
Logger.getInstance().print(id,
"\t[EMBARK] " + p.getName() + " at " + nextStop.getStopName());
} }
} catch (IndexOutOfBoundsException e) { } catch (IndexOutOfBoundsException e) {
Logger.getInstance().print(id, "Exception: " + e.getMessage()); Logger.getInstance().print(id, "Exception: " + e.getMessage());
@ -188,7 +189,6 @@ public class Bus extends Thread {
Logger.getInstance().print(id, "\t".repeat(indent) + "current stop: " + nextStop.getStopName()); Logger.getInstance().print(id, "\t".repeat(indent) + "current stop: " + nextStop.getStopName());
Logger.getInstance().print(id, "\t".repeat(indent) + "stops: "); Logger.getInstance().print(id, "\t".repeat(indent) + "stops: ");
if (nextStop != stops.get(0)) if (nextStop != stops.get(0))
nextStop.printDetails(id, indent + 1); nextStop.printDetails(id, indent + 1);
for (Stop s : stops) { for (Stop s : stops) {

View file

@ -1,24 +1,57 @@
package usherbrooke.ift630; package usherbrooke.ift630;
public class Passenger { import java.util.concurrent.Future;
import java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
private String name; public class Passenger extends Thread {
private int id;
private Stop dest;
private Stop start;
Passenger(int id, Stop start, Stop dest) { private String name;
private int id;
private Stop dest;
private Stop start;
private ExecutorService threads;
private ExecutorService ex;
private Future<Void> future;
Passenger(int id, Stop start, Stop dest) {
this.id = id; this.id = id;
this.name = "Passenger " + id; this.name = "Passenger " + id;
this.dest = dest; this.dest = dest;
this.start = start; this.start = start;
} this.ex = Executors.newFixedThreadPool(2); // one for each future.
}
// unused, *yet* public void run() {
public synchronized void embark() {} try {
embark();
disembark();
} catch (Exception e) {
Logger.getInstance().print(id, "[PASSENGER] " + e.toString());
}
}
// unused, *yet* // embark people once thread notified
public synchronized void disembark() {} private synchronized Future<Void> embark() {
return ex.submit(() -> {
synchronized (this) {
wait();
}
Logger.getInstance().print(id, "\t[PASSENGER] I'm embarking at " + start.getStopName());
return null;
});
}
// disembark people once thread notified another time.
private synchronized Future<Void> disembark() {
return ex.submit(() -> {
synchronized (this) {
wait();
}
Logger.getInstance().print(id, "\t[PASSENGER] I'm leaving at " + dest.getStopName());
return null;
});
}
public Stop getStart() { public Stop getStart() {
return start; return start;
@ -28,24 +61,31 @@ public class Passenger {
return dest; return dest;
} }
public String getName() { public String getPassengerName() {
return name; return name;
} }
// Pretty print, with color! // Pretty print, with color!
public void printDetails(int color, int indent) { public void printDetails(int color, int indent) {
Logger.getInstance().print(color, "\t".repeat(indent) + "---".repeat(3) + " Passenger details " + "---".repeat(3)); Logger.getInstance().print(color,
Logger.getInstance().print(color, "\t".repeat(indent) + name + " start: " + start.getStopName() + " dest: " + dest.getStopName()); "\t".repeat(indent) + "---".repeat(3) + " Passenger details " + "---".repeat(3));
Logger.getInstance().print(color,
"\t".repeat(indent) + name + " start: " + start.getStopName() + " dest: " + dest.getStopName());
} }
// Pretty print, with indent! // Pretty print, with indent!
public void printDetails(int indent) { public void printDetails(int indent) {
Logger.getInstance().print(id, "\t".repeat(indent) + "---".repeat(3) + " Passenger details " + "---".repeat(3)); Logger.getInstance().print(id, "\t".repeat(indent) + "---".repeat(3) + " Passenger details " + "---".repeat(3));
Logger.getInstance().print(id, "\t".repeat(indent) + name + " start: " + start.getStopName() + " dest: " + dest.getStopName()); Logger.getInstance().print(id,
"\t".repeat(indent) + name + " start: " + start.getStopName() + " dest: " + dest.getStopName());
} }
// Pretty print! // Pretty print!
public void printDetails() { public void printDetails() {
printDetails(0); printDetails(0);
} }
public void setThreadPool(ExecutorService threads) {
this.threads = threads;
}
} }

View file

@ -1,21 +1,21 @@
package usherbrooke.ift630; package usherbrooke.ift630;
import java.util.ArrayList; import java.util.concurrent.Executors;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.ArrayList;
public class Stop extends Thread { public class Stop extends Thread {
private String name; private String name;
private int id; private int id;
private int maxCapacity; private int maxCapacity;
private int indent = 0; private int indent = 0;
private ArrayList<Passenger> passengers; private ArrayList<Passenger> passengers;
private ExecutorService threads; private ExecutorService threads;
private BlockingQueue<BusInformationMessage> blockingQueue; private BlockingQueue<BusInformationMessage> blockingQueue;
// print bus info times. // print bus info times.
private void displayInfos(int indent) throws InterruptedException, ExitException{ private void displayInfos(int indent) throws InterruptedException, ExitException {
BusInformationMessage info = null; BusInformationMessage info = null;
// lock queue, get head // lock queue, get head
@ -30,7 +30,8 @@ public class Stop extends Thread {
Logger.getInstance().print(id, Logger.getInstance().print(id,
"\t".repeat(indent) + "[STOP] " + info.getBus(this).getNameBus() + " arrives in " + time + "s"); "\t".repeat(indent) + "[STOP] " + info.getBus(this).getNameBus() + " arrives in " + time + "s");
// else, catch // else, catch
} catch (NullPointerException e) {} } catch (NullPointerException e) {
}
} catch (UnauthorizedException e) { } catch (UnauthorizedException e) {
// if unauth, requeue message. // if unauth, requeue message.
@ -41,8 +42,13 @@ public class Stop extends Thread {
// loop, and ensure that every stop is reactive // loop, and ensure that every stop is reactive
synchronized (this) { synchronized (this) {
threads.submit(this); // i dont have access to virtual threads, and futures are for the next question.
// to not hog allof the pool's capacity,
// i have to manualy change threads in action. This is done by submiting this
// thread, waiting a bit (dont blow up our CPU) then exit. This ensure that
// another thread takes the slot, if it there is one.
sleep(10); sleep(10);
threads.submit(this);
throw new ExitException(); throw new ExitException();
} }
} }
@ -53,7 +59,8 @@ public class Stop extends Thread {
for (;;) { for (;;) {
displayInfos(indent); displayInfos(indent);
} }
} catch (InterruptedException | ExitException e) {} } catch (InterruptedException | ExitException e) {
}
} }
Stop(int id, int maxCapacity) { Stop(int id, int maxCapacity) {
@ -118,7 +125,7 @@ public class Stop extends Thread {
printDetails(0); printDetails(0);
} }
public void removePassenger(Passenger p) { public synchronized void removePassenger(Passenger p) {
try { try {
passengers.remove(p); passengers.remove(p);
} catch (Exception e) { } catch (Exception e) {