I am trying to figure out the passengers' disembark and embark methods in my project. The problem is the passengers' count will not be in order and I couldn't figure out which flights are ongoing those disembark and embarking actions. Objective: To figure out the way to add the flight number for passengers.
package airport_ccp;
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class airport_CCP {
public static void main(String[] args) {
Random rand = new Random();
Passengers passsenger = new Passengers();
//runway only got one, two gates
//runway is exclusive event, remain inclusive event for gates only
//gates available: 2, so create blockingqueue<runway>(2)
BlockingQueue<Gate> gates = new ArrayBlockingQueue<Gate>(2);
//threadpool for aircraft, two gates available
//so create a fixed threadpool for gates with 2 maximum
ExecutorService threadpool = Executors.newFixedThreadPool(2);
// 2 active inbound for 2 gates.
for (int i = 1; i <= 2; i++) {
gates.add(new Gate(i));
}
//10 flights
for(int i = 1; i <= 10; i++) {
try {
// 3 secnonds hold for new aircraft
Thread.sleep(rand.nextInt(3000));
threadpool.submit(new Aircraft(i, "land", gates));
//initial thought of input
ExecutorService executor = Executors.newCachedThreadPool();
for(int j=0; j<50; j++){
executor.submit(new Runnable() {
public void run() {
Passengers.getInstance().run();
}
});
}
executor.shutdown();
//input ends
} catch (InterruptedException e) {
e.printStackTrace();
}
}
threadpool.shutdown();
try {
if (threadpool.awaitTermination(100, TimeUnit.SECONDS)) {
for (int i = 1; i <= 2; i++) {
gates.take().printReport();
}
}
} catch (InterruptedException e) {
}
}
}
Below is my passenger class
package airport_ccp;
import java.util.Random;
import java.util.concurrent.Semaphore;
public class Passengers {
private static Passengers instance = new Passengers();
private Semaphore sema = new Semaphore(50, true); //set max to 50
private int passengercount = 0;
private Passengers() {
}
public static Passengers getInstance(){
return instance;
}
public void run() {
try {
sema.acquire();
System.out.println( "MH " /*ID input*/ + " : Passengers " + passengercount + " Disembarking");
} catch (InterruptedException ex) {
ex.printStackTrace();
}
try {
dorun();
}
finally {
System.out.println( "MH " /*ID input*/ + " : Passengers " + passengercount + " Embarking");
sema.release();
}
}
public void dorun() {
synchronized (this) {
passengercount++;
}
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
synchronized (this) {
passengercount--;
}
}
}
Aircraft class if there's any concern
package airport_ccp;
import java.util.Date;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
public class Aircraft implements Runnable{
String status;
int ID;
Date arrival;
BlockingQueue<Gate> gatescount = null;
Gate gate;
public Aircraft(int ID, String status, BlockingQueue<Gate> gatescount) {
this.ID = ID;
this.gatescount = gatescount;
System.out.println("\t Time : " + java.time.LocalDateTime.now() + "\t" + " MH " + ID + " is calling for landing.");
}
@Override
public void run() {
try {
this.status = "land";
gate = gatescount.take();
System.out.println("\t MH " + ID + " has been assigned to " + gate.getName() + ".");
System.out.println( "\t Time : " + java.time.LocalDateTime.now() + "\t" + " MH " + ID + " is " + status + ".");
//Thread.sleep(1000*(1+new Random().nextInt(10)));
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
gate.inc(status);
this.status="depart";
System.out.println("\t Time : " + java.time.LocalDateTime.now() + "\t" + "MH " + ID + " has " + status);
gatescount.add(gate);
}
Err - why do you not pass in the flight number into the run
method?
// in Passengers
public void run(int id) {
try {
sema.acquire();
System.out.println( "MH " + id + " : Passengers " + passengercount + " Disembarking");
} catch (InterruptedException ex) {
ex.printStackTrace();
}
try {
dorun();
}
finally {
System.out.println( "MH " + id + " : Passengers " + passengercount + " Embarking");
sema.release();
}
}
// when calling Passengers: pass in that ID
for(int i = 1; i <= 10; i++) {
try {
/* ... */
for(int j=0; j<50; j++){
int id = i; // <-- copy to a constant value; once assigned, id is never changed
executor.submit(new Runnable() {
public void run() {
Passengers.getInstance().run(id);
}
});
}
/* ... */
Note that the previous version used this code, which produces an error because the value of i
changes in each iteration, while Java needs to ensure that it stays constant; using a reference that does not change (as above) solves the problem:
for(int j=0; j<50; j++){
executor.submit(new Runnable() {
public void run() {
Passengers.getInstance().run(i); // <-- fails, because i is not, and cannot be made, final
}
});
}