Search code examples
javaconcurrencyjava.util.concurrent

Java Concurrent: trying to identify my passengers are from which flight


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);
    }

Solution

  • 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
                        }                    
                    });
                }